Когда изменяется состояние реагирующего компонента, вызывается метод визуализации. Следовательно, для любого изменения состояния действие может быть выполнено в теле методов рендеринга. Существует ли конкретный вариант использования для обратного вызова setState?
Да, так как setState
работает asynchronous
. Это означает, что после вызова setState
переменная this.state
не изменяется немедленно. так что если вы хотите выполнить действие сразу после установки состояния для переменной состояния и затем вернуть результат, обратный вызов будет полезен
Рассмотрим пример ниже
....
changeTitle: function changeTitle (event) {
this.setState({ title: event.target.value });
this.validateTitle();
},
validateTitle: function validateTitle () {
if (this.state.title.length === 0) {
this.setState({ titleError: "Title can't be blank" });
}
},
....
Приведенный выше код может работать не так, как ожидалось, поскольку переменная title
может не мутировать до того, как будет выполнена проверка. Теперь вы можете задаться вопросом, что мы можем выполнить проверку в самой функции render()
, но было бы лучше и чище, если бы мы могли обрабатывать это в самой функции changeTitle, так как это сделало бы ваш код более организованным и понятным
В этом случае обратный вызов полезен
....
changeTitle: function changeTitle (event) {
this.setState({ title: event.target.value }, function() {
this.validateTitle();
});
},
validateTitle: function validateTitle () {
if (this.state.title.length === 0) {
this.setState({ titleError: "Title can't be blank" });
}
},
....
Другой пример будет, когда вы хотите dispatch
и действие, когда состояние изменилось. Вы захотите сделать это в обратном вызове, а не в render()
как он будет вызываться каждый раз, когда происходит повторное рендеринг, и, следовательно, возможны многие такие сценарии, когда вам потребуется обратный вызов.
Другой случай - API Call
Может возникнуть ситуация, когда вам нужно сделать вызов API на основе определенного изменения состояния, если вы сделаете это в методе рендеринга, он будет вызываться при каждом изменении рендеринга onState
или из-за изменения некоторого пропуска, передаваемого onState
Child Component
.
В этом случае вы захотите использовать setState callback
для передачи обновленного значения состояния в вызов API
....
changeTitle: function (event) {
this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
// Call API with the updated value
}
....
1. usecase, который приходит мне на ум, является вызовом api
, который не должен входить в рендер, потому что он будет работать для изменения состояния each
. И вызов API должен выполняться только при специальном изменении состояния, а не в каждом рендере.
changeSearchParams = (params) => {
this.setState({ params }, this.performSearch)
}
performSearch = () => {
API.search(this.state.params, (result) => {
this.setState({ result })
});
}
Следовательно, для любого изменения состояния действие может выполняться в теле методов рендеринга.
Очень плохая практика, потому что метод render
должен быть чистым, это означает, что никакие действия, изменения состояния, вызовы api не должны выполняться, просто составьте ваше представление и верните его. Действия должны выполняться только для некоторых событий. Render - это не событие, а componentDidMount
например.
this.setState({
name:'value'
},() => {
console.log(this.state.name);
});
setState является асинхронной функцией
Таким образом, вы не можете на это сильно полагаться. Например, давайте рассмотрим время t = 0. Две функции setState были вызваны в вашем приложении из разных точек вашего приложения. До t = 0 они ссылались на одно и то же состояние. При одновременном срабатывании они изменят только это состояние. Предположим, что один из них завершил выполнение при t = 3, таким образом, изменил состояние и создал новое состояние (вызовите его как состояние_1). Теперь второй setState завершил работу в t = 4. Он изменен в исходном состоянии и создал новое состояние (называется его как состояние_2). Это новое состояние (состояние_2) отличается от состояния_1. И, таким образом, мы можем иметь несоответствие данных.
Таким образом, всякий раз, когда ваше новое состояние зависит от предыдущего состояния, используйте метод обратного вызова состояния. prevState всегда относится к состоянию, которое является результатом последнего изменения в памяти. Таким образом, функция обратного вызова, использующая prevState, никогда не вызывает расхождения в данных.
Неправильный код:
this.setState(
{counter:this.state.counter+1}
);
Правильный код с setState с функцией обратного вызова:
this.setState(
(prevState,props)=>{
return {counter:prevState.counter+1};
}
);
В общем случае обратные вызовы используются для запуска некоторого кода, когда что-то произошло. Обновление состояния при успешном вызове setState.