React setState не обновляется немедленно
Я работаю над приложением todo. Это очень упрощенная версия оскорбительного кода. У меня есть флажок:
<p><input type="checkbox" name="area" checked={this.state.Pencil} onChange={this.checkPencil}/> Writing Item </p>
вот функция, которая вызывает флажка:
checkPencil(){
this.setState({
pencil:!this.state.pencil,
});
this.props.updateItem(this.state);
}
updateItem-это функция, которая отображается для отправки в redux
function mapDispatchToProps(dispatch){
return bindActionCreators({ updateItem}, dispatch);
}
моя проблема в том, что когда я вызываю действие updateItem и консоль.регистрируйте состояние, оно всегда на 1 шаг позади. Если флажок снят и не true, я все равно получаю состояние true передается функции updateItem. Нужно ли вызывать другую функцию, чтобы заставить состояние обновляться?
8 ответов
вы должны вызвать свою вторую функцию в качестве обратного вызова setState, так как setState происходит асинхронно. Что-то вроде:
this.setState({pencil:!this.state.pencil}, myFunction)
однако в вашем случае, так как вы хотите, чтобы эта функция вызывалась с параметром, вам придется немного более творчески и, возможно, создать свою собственную функцию, которая вызывает функцию в реквизите:
myFunction = () => {
this.props.updateItem(this.state)
}
объедините их вместе, и это должно сработать.
вызов setState()
in React является асинхронным по различным причинам (в основном производительность). Под обложками React будет пакетировать несколько вызовов setState()
в одну мутацию состояния, а затем повторно визуализировать компонент один раз, а не повторно визуализировать для каждого изменения состояния.
к счастью, решение довольно простое - setState
принимает параметр обратного вызова:
checkPencil(){
this.setState({
pencil:!this.state.pencil,
}, function () {
this.props.updateItem(this.state);
}.bind(this));
}
когда вы обновляете свое состояние, используя свойство текущего состояния, документация React советует вам использовать версию вызова функции setState
вместо объекта.
так setState((state, props) => {...})
вместо setState(object)
.
причина в том, что setState
- это скорее запрос на изменение состояния, а не немедленное изменение. Реагируйте партиями те setState
призывы к повышению производительности.
означает, что государственное свойство, которое вы проверяете, может не быть стабильный. Это потенциальная ловушка, о которой нужно знать.
для получения дополнительной информации см. документацию здесь:https://facebook.github.io/react/docs/react-component.html#setstate
чтобы ответить на ваш вопрос, я бы сделал это.
checkPencil(){
this.setState((prevState) => {
return {
pencil: !prevState.pencil
};
}, () => {
this.props.updateItem(this.state)
});
}
потому что асинхронно, так что означает, что в это время может не обновляться еще...
согласно документации React v. 16, вам нужно использовать вторую форму setState()
который принимает функцию, а не объект:
Обновления Состояния Могут Быть Асинхронными
React может пакетировать несколько вызовов setState() в одно обновление для спектакль.
потому что это.реквизит и это.состояние может быть обновлено асинхронно, вы не следует полагаться на их значения для вычисления следующего состояния.
например, этот код может не обновить счетчик:
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
чтобы исправить это, используйте вторую форму setState (), которая принимает функцию а не объект. Эта функция получит предыдущее состояние в качестве первого аргумента и реквизита во время применения обновления в качестве второго аргумента:
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
я использовал оба предложения rossipedia и Ben Hare и сделал следующее:
checkPencil(){
this.setState({
pencil:!this.state.pencil,
}, this.updatingItem);
}
updatingItem(){
this.props.updateItem(this.state)
}
У Бена есть отличный ответ на то, как решить непосредственную проблему, однако я бы также посоветовал избегать дублирования состояния
Если состояние находится в redux, ваш флажок должен считывать свое собственное состояние из prop или store вместо отслеживания состояния проверки как в своем собственном компоненте, так и в глобальном магазине
сделать что-то вроде этого:
<p>
<input
type="checkbox"
name="area" checked={this.props.isChecked}
onChange={this.props.onChange}
/>
Writing Item
</p>
общее правило состоит в том, что если вы найдете состояние, необходимое в нескольких местах, поднимите его до общего родитель (не всегда redux), чтобы поддерживать только один источник истины
попробуй такое
this.setState({inputvalue: e.target.value}, function () {
console.log(this.state.inputvalue);
this.showInputError(inputs[0].name);
});
функция showInputError для проверки при использовании любых форм
установить значение. после приступайте к своим работам.
this.setState({inputvalue: e.target.value}, function () {
this._handleSubmit();
});
_handleSubmit() {
console.log(this.state.inputvalue);
//Do your action
}