0

I have a state variable called list that updates when setList is called. SetList lives under the function AddToList, which adds a value to the existing values in the list. As of this moment, the function handleList executes prior to the state variable setList even though I have setList added prior to the function handleList. What I am trying to achieve is for the setList to update its list prior to running the handleList. Could you provide insights on how to fix this?

If you want to test the code, https://codesandbox.io/s/asynchronous-test-mp2fq?file=/Form.js

export default function Form() {
  const [list, setList] = useState([]);

  const addToList = (name) => {
    let newDataList = list.concat(name);
    setList(newDataList);
    console.log("List: ", list);
    handleList();
  };

  const handleList = async () => {
    console.log("Handle List Triggered");
    await axios
      // .put("", list)
      .get("https://api.publicapis.org/entries")
      .then((response) => {
        console.log("Response: ", response);
      })
      .catch((error) => {});
  };

  return (
    <AutoComplete
      name="list"
      label="Add to List"
      onChange={(events, values) => {
        addToList(values.title);
      }}
    />
  );
}

enter image description here

As you can tell, the get response is made prior to updating the list.

May
  • 61
  • 1
  • 6
  • `What I am trying to achieve is for the setList to update its list prior to running the handleList` - this is the definition of `useEffect` – Adam Jenkins Aug 13 '21 at 17:01

3 Answers3

2

It's not clear what you want to do with the updated list, but you know what the new list will be, so you can just pass that around if you need it immediately.

  const addToList = (name) => {
    let newDataList = list.concat(name);
    setList(newDataList);
    console.log("List: ", list);
    handleList(newDataList);
  };

  const handleList = async (list) => {
    console.log("Handle List Triggered");
    await axios
      // .put("", list)
      .get("https://api.publicapis.org/entries")
      .then((response) => {
        console.log("Response: ", response);
      })
      .catch((error) => {});
  };
spender
  • 117,338
  • 33
  • 229
  • 351
2

React's useEffect hook has an array of dependencies that it watches for changes. While a lot of the time it's used with no dependencies (i.e. no second parameter or empty array) to replicate the functionality of componentDidMount and componentDidUpdate, you may be able to use that to trigger handleList by specifying list as a dependency like this:

useEffect(() => {
  handleList(list);
}, [list]);

I think there may be a redundant request when page loads though because list will be populated which you'll most likely want to account for to prevent unnecessary requests.

Dillan Wilding
  • 1,030
  • 2
  • 12
  • 28
1

first of all you have to understand setState is not synchronized that means when you call setList(newDataList) that not gonna triggered refer why setState is async therefore you can use @spender solution or useStateCallback hook but it's important understand setState is not sync

   const [state, setState] = useStateCallback([]);
   const addToList = (name) => {
   ........... your code
   setList(newDataList, () => {
      // call handleList function here
         handleList();
    }); 
    }
Inshaf Ahmed
  • 401
  • 6
  • 8