Welcome to JiKe DevOps Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
111 views
in Technique[技术] by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

Please log in or register to answer this question.

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to JiKe DevOps Community for programmer and developer-Open, Learning and Share
...