Когда использовать обратный вызов React setState

99

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

  • 4
    В настоящее время неясно, о чем вы спрашиваете. Можете ли вы включить код?
  • 1
    Обратный вызов setState предназначен для всего, что вы хотите сделать после того, как состояние ОПРЕДЕЛЕНО было изменено. Поскольку setState является асинхронным, если вы хотите вызвать fx и быть уверенным, что новое состояние загружено, то для этого и нужен обратный вызов
Показать ещё 1 комментарий
Теги:
callback
setstate

4 ответа

138

Да, так как 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
    Я понимаю, что это асинхронный характер. Мой вопрос был о том, есть ли что-то конкретное, что только обратный вызов setState может быть использован для этого, возможно, тело методов рендеринга может не поддерживать (что-то кроме, скажем, лучшей читабельности кода).
  • 0
    @SahilJain Validation - правильный пример, вы не захотите обрабатывать его в функции render (), потому что тогда он будет вызываться каждый раз, когда вы вносите какие-либо изменения в render (), вы хотите вызывать его только тогда, когда изменяется только вход, и, следовательно, в самой функции
Показать ещё 4 комментария
36

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 например.

12
this.setState({
    name:'value' 
},() => {
    console.log(this.state.name);
});
  • 8
    Спасибо за этот фрагмент кода, который может предоставить некоторую ограниченную, немедленную помощь. Правильное объяснение значительно улучшило бы его долгосрочную ценность , показав, почему это хорошее решение проблемы, и сделало бы его более полезным для будущих читателей с другими, похожими вопросами. Пожалуйста, измените свой ответ, чтобы добавить некоторые объяснения, в том числе предположения, которые вы сделали.
  • 0
    Когда вы хотите вызвать функцию после изменения состояния, вы можете использовать метод.
Показать ещё 1 комментарий
10

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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню