Асинхронный способ получения последнего изменения состояния с помощью реактивных крючков

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я начал изучать React и разрабатывать приложение с использованием ReactJS. Недавно я перешел на React Hooks. Я знаю, что в компоненте класса мы можем получать последние данные из состояния со 2-м аргументом, который присутствует в setState(), например

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

Я хотел знать, есть ли какие-либо аргументы в реактивных перехватах, с помощью которых мы можем получить из него последние данные.
Я использую перехватчики реакции описанным ниже способом, но при регистрации консоли он всегда возвращает предыдущее состояние
Например, перехваты:

 const [socialData, setSocialData] = useState([
        { id: new Date().getTime().toString(), ...newItem }
    ]);
const onChangeCallback = (index, type, data) => {
    let newSocialData = [...socialData];
    newSocialData[index] = { ...newSocialData[index], [type]: data };
    setSocialData(newSocialData);
    onInputChange(newSocialData, formKey);
    console.log(newSocialData); 
};
 

Комментарии:

1. В реактивных перехватах вы должны воспользоваться перехватом useState, это было бы что-то вроде const [name, setName] = useState(‘ ‘) затем вы обновляете состояние с помощью setName, который ведет себя так же, как setState в компоненте класса reactjs.org/docs/hooks-intro.html

2. Да, я уже использую useState . Но когда я устанавливаю состояние name и регистрирую его в консоли, оно регистрирует старое значение.

Ответ №1:

this.setState() Второй аргумент заключается не в том, чтобы получить последние данные из состояния, а в том, чтобы запустить некоторый код после того, как состояние было эффективно изменено.

Помните, что установка состояния является асинхронной операцией. Это связано с тем, что React необходимо дождаться других потенциальных запросов на изменение состояния, чтобы он мог оптимизировать изменения и выполнить их в одном обновлении DOM.

С this.setState() помощью вы можете передать функцию в качестве первого аргумента, которая получит последнее известное значение состояния и должна вернуть новое значение состояния.

 this.setState((previousState) => {
  const newState = previousState   1;
  return newState;
}, () => {
  console.log('State has been updated!')
});
 

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

Обычно во время выполнения обратного вызова, такого как ваш onChangeCallback , вы хотите изменить состояние в качестве последнего, что делает ваша функция. Если вы уже знаете новое значение состояния, почему вы хотите дождаться изменения реального состояния, чтобы использовать его?

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

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

 import React, {useState, useEffect, useCallback} from 'react';

function MyComponent() {
  const [value, setValue] = useState(false);

  const onChangeHandler = useCallback((e) => {
    setValue(!!e.target.checked);
  }, []);

  useEffect(() => {
    // THIS WILL RUN ONLY WHEN value CHANGES. VERY SIMILAR TO WHAT YOU ARE TRYING TO DO WITH THE this.setState SECOND ARGUMENT.
  }, [value]);

  return (
    <input type='checkbox' onChange={onChangeHandler} />
  );
}
 

Существует также способ создать пользовательский useState перехват, позволяющий передавать второй аргумент setValue и имитировать поведение this.setState , но внутренне он будет делать именно то, что я сделал в вышеупомянутом компоненте. Пожалуйста, дайте мне знать, если у вас есть какие-либо сомнения.