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

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

Ответ 1

Да, так как 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
}
....

Ответ 2

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

Ответ 3

this.setState({
    name:'value' 
},() => {
    console.log(this.state.name);
});

Ответ 4

Рассмотрим вызов setState

this.setState({ counter: this.state.counter + 1 })

setState может быть вызван в асинхронной функции

Так что на this нельзя полагаться. Если вышеупомянутый вызов был сделан внутри асинхронной функции, this будет ссылаться на состояние компонента в тот момент времени, но мы ожидали, что это будет ссылаться на свойство внутри состояния во время вызова setState или начала асинхронной задачи. И поскольку заданием был асинхронный вызов, то это свойство могло со временем измениться. Таким образом, ненадежно использовать this ключевое слово для ссылки на какое-либо свойство состояния, поэтому мы используем функцию обратного вызова, аргументы которой - previousState и props, что означает, что когда была выполнена асинхронная задача, и пришло время обновить состояние с помощью вызова setState, prevState теперь будет ссылаться на состояние, когда setState еще не запущен. Обеспечение надежности, что nextState не будет поврежден.

Неверный код: приведет к повреждению данных

this.setState(
   {counter:this.state.counter+1}
 );

Правильный код с setState с функцией обратного вызова:

 this.setState(
       (prevState,props)=>{
           return {counter:prevState.counter+1};
        }
    );

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