setState вне событий синтетического реагирования - PullRequest
0 голосов
/ 29 декабря 2018
class Hello extends React.Component {
    constructor(props){
        super(props)
            this.state={count:1};
            this.myRef = React.createRef();
        }
        use(){
            console.log(this.myRef);
            let f=function(){
            this.setState({count:2});
            console.log("in f" + this.state.count);
        }
        //let a=React.findDOMNode(this.myRef.current);
        this.myRef.current.onclick=f.bind(this);
        //console.log(a);
    }

    render() {
        console.log("in render"+" "+this.state.count);
        return (
            <div>Hello {this.state.count}
                <div onClick={this.use.bind(this)}>add function</div>
                <button ref ={this.myRef}>click</button>
            </div>;
        )
    }
}

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

В этом коде 'console.log ("in f" + this.state.count)' выполняется после 'console.log ("in render" + "" + this.state.count)', которыйвозможно только в том случае, если setState является синхронным вызовом функции, которая внутренне вызывает другую синхронную функцию render. Но согласно responsejs setState является асинхронным, поэтому сначала необходимо выполнить console.log ("in f" + this.state.count) '. Почемуведет себя так?

1 Ответ

0 голосов
/ 29 декабря 2018

Это относится к пакетным обновлениям .В приведенном выше коде f прослушиватель событий добавляется вручную, событие щелчка вызывается вне жизненного цикла React.Обновления состояния не пакетируются, а происходят синхронно.Это может отрицательно повлиять на производительность, если обновления состояния могут выиграть от пакетной обработки.

Вот более простые примеры, показывающие, как это работает.

Пример 1

Обновление состоянияпроисходит внутри жизненного цикла React, он пакетный и асинхронный.

  f = () => {
    this.setState({count:2});
    console.log("in f" + this.state.count);
  }

  render() {
    console.log("in render"+" "+this.state.count);

    return <div>
      Hello {this.state.count}
      <button onClick={this.f}>click</button>
    </div>;
  }

Вывод:

в f1

при рендеринге 2

Пример 2

Обновление состояния происходит вне жизненного цикла React, оно пакетное и синхронное.

  f = () => {
    setTimeout(() => {
      this.setState({count:2});
      console.log("in f" + this.state.count);
    })
  }
  ...

Вывод:

при рендеринге 2

в f2

Пример 3

Обновление состояния снова пакетное и асинхронное.

  f = () => {
    setTimeout(() => {
      ReactDOM.unstable_batchedUpdates(() => {
        this.setState({count:2});
        console.log("in f" + this.state.count);
      });
    })
  }
  ...

Вывод:

в f1

в рендере 2


Что касается findDOMNode, это связано с DOM, как следует из названия.Это ReactDOM.findDOMNode, а не React.findDOMNode.

...