Как полагаться на this.props при расчете нового состояния может испортить мое приложение React? - PullRequest
0 голосов
/ 13 марта 2019

Документация React многое говорит о том, что setState() является асинхронным и последствия этой черты.
В частности, это говорит :

Поскольку this.props и this.state могут обновляться асинхронно, вы не должны полагаться на их значения для вычисления следующего состояния.

И это также дает хорошие примеры того, почему использование this.props может (и будет) нарушать ваш код. Один из них (с здесь ):

// multiple call like this
this.setState({ quantity: state.quantity + 1 });

// may be batched and will result in the equivalent of
Object.assign(
    previousState,
    { quantity: state.quantity + 1 },
    { quantity: state.quantity + 1 },
    ...
 );

Примеры очень иллюстративны и полезны для понимания асинхронной природы обновления состояния.

К сожалению, я не могу найти подобных примеров использования this.props при обновлении состояния.
Может ли кто-нибудь помочь мне с этим? Я хотел бы видеть минимальный иллюстративный код, но если у вас есть огромный реальный пример, он тоже будет великолепен. :)

Спасибо.

1 Ответ

1 голос
/ 13 марта 2019

Вы можете передать функцию в качестве первого аргумента setState. Эта функция получает состояние и реквизиты в качестве аргументов, а объект, который вы возвращаете из этой функции, будет использоваться для обновления состояния.

Пример

this.setState((state, props) => ({ counter: state.counter + props.step }))

Один из способов увидеть, что это важно, - это когда вы вызываете функцию в дочернем компоненте, что может привести к тому, что родительский компонент изменит реквизиты, данные дочернему компоненту. Если вы обратитесь к this.props, вы получите устаревшее значение.

Пример

class Counter extends React.Component {
  state = {
    counter: 0
  };

  onClick = () => {
    this.props.onIncrement();

    this.setState({ counter: this.state.counter + this.props.step });
    // This works
    // this.setState((state, props) => ({ counter: state.counter + props.step }));
  };

  render() {
    return <button onClick={this.onClick}>{this.state.counter}</button>;
  }
}

class App extends React.Component {
  state = {
    step: 0
  };

  incrementStep = () => {
    this.setState(({ step }) => ({ step: step + 1 }));
  };

  render() {
    return <Counter step={this.state.step} onIncrement={this.incrementStep} />;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...