2016-07-27 2 views
0

Я новичок в ReactJS, и я не могу показаться, чтобы выяснить, почему результат следующей SetState не как я ожидаю, что это (т.е. для увеличения значения каждую секунду на 1)SetState в ReactJS

import React from 'react'; 
import ReactDOM from 'react-dom'; 

class Layout extends React.Component { 

    constructor() { 
     super(); 
     this.state = { 
      name: "Behnam", 
      i: 0 
     } 
    } 

    render() { 

     setInterval(() => { 
      this.setState({ name : "Behnam" + this.state.i }); 
      this.setState({ i: this.state.i + 1 }); 
     }, 1000); 

     return (
      <div className="container"> 
       {this.state.name} 
      </div> 
     ); 
    } 
} 

ReactDOM.render(<Layout />, document.getElementById('app')); 

Вместо этого строка вывода быстро увеличивается (я думаю, так же быстро, как реагировать, пытается сохранить ее «обновленный виртуальный DOM»). Поэтому мне было интересно, как правильно это сделать?

+1

Вы сделали это неправильно. Знайте, что setState вызовет метод рендеринга, поэтому в вашем коде вы сделали какой-то цикл рендеринга> setState> render> setState .... Хорошим способом является setInterval внутри метода componentDidMount для реагирования на жизненный цикл компонента (https://facebook.github.io/react/docs/component-specs.html), поэтому ваш рендер будет только декларативным –

ответ

4

Каждый раз, когда вы меняете состояние, вы выполняете перезагрузку компонента. Поскольку вы инициировали метод рендеринга setInterval, вы получаете еще один интервал, который изменяет состояние и редерты и т. Д.

Перемещение setInterval к componentDidMount, который вызывается только один раз, когда компонент крепления:

import React from 'react'; 
import ReactDOM from 'react-dom'; 

class Layout extends React.Component { 

    constructor() { 
     super(); 
     this.state = { 
      name: "Behnam", 
      i: 0 
     } 
    } 

    componentDidMount() { set the interval after the component mounted, and save the reference 
     this.interval = setInterval(() => { 
      this.setState({ 
       name: `Behnam${this.state.i}`, 
       i: this.state.i + 1 
      }); 
     }, 1000); 
    } 

    componentWillUnmount() { 
     this.interval && clearInterval(this.interval); // clear the interval when the component unmounts 
    } 

    render() { 
     return (
      <div className="container"> 
       {this.state.name} 
      </div> 
     ); 
    } 
} 

ReactDOM.render(<Layout />, document.getElementById('app')); 
1

В настоящее время он создает интервал каждый времени компонент оказывается, таким образом, есть несколько таймеров Инкрементирование Значение. Вероятно, вы захотите сделать это в componentDidMount() вместо render(). См. docs.

import React from 'react'; 
import ReactDOM from 'react-dom'; 

class Layout extends React.Component { 

    constructor() { 
     super(); 
     this.state = { 
      name: "Behnam", 
      i: 0 
     } 
    } 

    componentDidMount() { 
     setInterval(() => { 
      this.setState({ name : "Behnam" + this.state.i }); 
      this.setState({ i: this.state.i + 1 }); 
     }, 1000); 
    } 

    render() { 
     return (
      <div className="container"> 
       {this.state.name} 
      </div> 
     ); 
    } 
} 

ReactDOM.render(<Layout />, document.getElementById('app')); 
1

Каждый раз, когда рендер срабатывает, вы звоните setInterval снова, добавляя к числу активных интервалов на этой странице.

Возможно, вы должны использовать другой метод жизненного цикла, такой как componentDidMount. Не забудьте сохранить идентификатор интервала, возвращенный setInterval, чтобы вы могли позвонить clearInterval в componentWillUnmount.

Смежные вопросы