简体   繁体   中英

Asynchronous way to get the latest change in State with React Hooks

I have started learning React and developing an application using ReactJS. Recently i have moved to React Hooks. I know that in Class Component we can get the latest data from the state with the 2nd argument which is present in setState() like

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

I wanted to know if there is any arguments in React Hooks with which we can get the latest data from it. I am using React Hooks in the below mentioned way, but upon console logging it always return the previous state Hooks Eg:

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); 
};

The this.setState() second argument is not exactly to get the latest data from the state, but to run some code after the state has been effectively changed.

Remember that setting the state is an asynchronous operation. It is because React needs to wait for other potential state change requests so it can optimize changes and perform them in a single DOM update.

With this.setState() you can pass a function as the first argument, which will receive the latest known state value and should return the new state value.

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

With that being said, there are special and rare cases when you need to know exactly when the state change has taken place. In many years of working with React I only faced this scenario once and I consider it a desperate attempt to make things work.

Usually, during a callback execution, like your onChangeCallback you want to change the state as the last thing your function does. If you already know the new state value, why do you want to wait for the real state to change to use it?

The new state value should be a problem to be handled during the next render.

If you want to run some code only when that particular state value changes you can do something like this:

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} />
  );
}

There is also a way to create a custom useState hook, to allow you passing a second argument to setValue and mimic the behavior of this.setState , but internally it would do exactly what I did in the above component. Please let me know if you have any doubt.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM