Запрет this.state для использования с setState - PullRequest
0 голосов
/ 08 октября 2018

Ссылка заявляет:

setState () не всегда немедленно обновляет компонент.Это может пакетировать или отложить обновление до позже.Это делает чтение this.state сразу после вызова setState () потенциальной ловушкой.Вместо этого используйте componentDidUpdate или обратный вызов setState (setState (Updater, callback)), который гарантированно сработает после применения обновления.Если вам нужно установить состояние на основе предыдущего состояния, прочитайте об аргументе средства обновления ниже.

Поэтому в React считается ошибкой использовать this.state значения вместе с setState, потому что setState является асинхронным и может привести к обновлению состояния с неправильными значениями (a demo ):

// destructured
const { state, setState } = this;
setState({ foo: state.foo });

// destructured
const { foo } = this.state;
setState({ foo });

// undestructured
this.setState({ foo: this.state.foo });

Хотя это будет правильным способом обновления состояния (демо )):

// destructured
this.setState(({ foo }) => ({ foo }));

// undestructured
this.setState(state => ({ foo: state.foo }));

Существует ли правило ESLint или другой способ предотвратить некоторые или все из этих случаев, когда this.state может быть использовано не по назначению?

Я предполагаю, что это может быть сложно, номожно решить этот случай с помощью статического анализа.

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

eslint-plugin-реаги * выполнит эту проверку с реагировать / без доступа-в-состоянии-в-состоянии правило

Это правило должно предотвращатьиспользование this.state внутри вызовов setState.Такое использование this.state может привести к ошибкам, когда два вызова состояния вызываются в пакетном режиме и, таким образом, ссылаются на старое состояние, а не на текущее состояние.

0 голосов
/ 08 октября 2018

Если вы используете:

// destructured
const { state, setState } = this;
setState({ foo: state.foo });

Eslint все еще предупреждает вас из-за state.foo (доступ к свойству объекта).Чтобы избежать этого, вы можете определить как:

// destructured
const { state: { foo }, setState } = this;
setState({ foo });

Но если вы используете:

// undestructured
this.setState({ foo: this.state.foo });

Тогда ESLINT предупредит вас использовать синтаксис деструктурирования, например:

const { foo } = this.state
this.setState({foo})

Примечание: поскольку foo - это имя переменной для обновления, и имя совпадает, мы можем использовать только {foo} и оно совпадает с {foo: foo}.


Также, однако, япредпочитаю использовать синтаксис this.setState() вместо деструктуризации до this.Потому что в любом приложении мы используем this всякий раз, когда это необходимо.И использование const { ... } = this кажется странным, если мы посмотрим между кодом, когда видим setState, а не this.setState.Думая о третьем разработчике.


Из комментариев вы хотите обновлять состояние один за другим, тогда вы должны использовать обратный вызов, например:

onClick = () => {
   this.setState({ foo: 'Bar' }, () => {
      this.setState({ foo: this.state.foo + '!' });
   });
}

Теперь выВы сможете увидеть изменения в Hello Bar! в своей демонстрационной версии.

Если вы используете setState следующим образом:

onClick = () => {
   this.setState({ foo: 'Bar' })
   this.setState({ foo: this.state.foo + '!' });
   // obviously, better to use updater syntax though.
}

Тогда первый setState будет переопределен последним.И вы получите изменения к Hello Foo! в своей демоверсии.

Кроме того, в документации говорится то же самое.Синтаксис средства обновления - это просто удобный метод, но результат такой же, как и без синтаксиса средства обновления.Самая важная роль только с его синтаксисом обратного вызова.Синтаксис обратного вызова используется, чтобы вы могли получить доступ к обновленному состоянию сразу после его обновления.


Чтобы узнать больше о деструктурировании синтаксиса.Вы можете подписаться на мой другой пост , где вы можете найти подробную информацию и некоторые ссылки, которые будут для вас знакомы.

...