Home > Net >  How to setState and immiediately invoke it within the same function?
How to setState and immiediately invoke it within the same function?

Time:07-01

I'm writing a function that simultaneously sets state AND assigns it to an object.. I'm specifically talking about setValue and after: value

    const handleAddToHistory = (e) => {
    e.preventDefault();
    
    setValue((parseFloat(Object.values(data))*fromTo).toFixed(2))
    
    setHistory([ ... history , {
      date: new Date().toISOString().slice(0, 10),
      before: fromTo,
      after: value,
    }])
  }

However, on the first run "value" is empty. It forces me to click the button again, and only then it shows all the data properly.

How can I setState and immiediately invoke it ? Should I do some sort of Time Interval on setHistory to wait until setValue is actually set?

CodePudding user response:

When you set state in React, it's asynchronous, since it triggers a re-render. Therefore, you use useEffect to handle anything that needs to happen when value changes:

    useEffect(() => {
      setHistory([ ... history , {
          date: new Date().toISOString().slice(0, 10),
          before: fromTo,
          after: value,
       }])
    }, [value])

CodePudding user response:

Any reason to not do this?

    const handleAddToHistory = (e) => {
    e.preventDefault();
    
    const valueToSave = (parseFloat(Object.values(data))*fromTo).toFixed(2);
    setValue(valueToSave)
    
    setHistory([ ... history , {
      date: new Date().toISOString().slice(0, 10),
      before: fromTo,
      after: valueToSave,
    }])
  }

If that doesn't work for some reason, you can use a useEffect hook:

  const handleAddToHistory = (e) => {
    e.preventDefault();
    
    setValue(parseFloat(Object.values(data))*fromTo).toFixed(2))
  }
  useEffect(() => {
    setHistory([ ... history , {
      date: new Date().toISOString().slice(0, 10),
      before: fromTo,
      after: value,
    }]);
  }, [value]);
  • Related