skip to Main Content

I have a function that would trigger a set function and is expected to make use of the updated value to do sth else

Here is an example

export default function App() {

const [value,setValue] = useState(0)
  const increaseValueaAndAlertUpdatedValue = () => {
    setValue((prev)=>{return prev + 1})
    alert(`updated value: ${value}`) //expect the first click is to show the updated value, but not current value. It is not necessary to be plus, but I want the call back function here is to show the updated value after setValue when clicking it. 
  }
  return (
    <div className='App'>
      <h1>Hello React TypeScript.</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={increaseValueaAndAlertUpdatedValue}>increaseValueaAndAlertUpdatedValue</button>
    </div>
  );
}

I really need to make use of the updated value instead of the current value there. But now it seems the updated value could only be access after a re-rendering.

In my case, value is not a simple number value, it is a giant object.

Way I also tried: (wrapped it with a setTimeout) But, obviously, it doesnt work. I guess it is a problem of closure

setTimeout(()=>{ alert(`updated value: ${value}`)},1000)

useEffect and useLayoutEffect are not solution to my situation becuase I need the value after that the set function fired and use the updated value in my "alert function" ; not in other useEffect or layoutEffect.

3

Answers


  1. Can’t you perform the action in callback method passed in setValue.

    function App() {
      const [count, setCount] = useState(0);
    
      function handleClick() {
        setCount((prevCount) => {
          const newCount = prevCount + 1;
          runAlert(newCount); // ---> runAlert will show the alert
          return newCount;
        });
      }
    
      const runAlert = (state) => {
        setTimeout(() => {
          alert(state);
        }, 0); // --> required so it won't get executed as soon as alert is seen
      };
    
      return <button onClick={handleClick}>{count} Increase counter</button>;
    } 
    
    Login or Signup to reply.
  2. Why not to do something like this? You already know the new value inside your state update and alert function so you can call alert like this:

    import {useState} from 'react';
    import "./styles.css";
    
    export default function App() {
      const [value,setValue] = useState(0)
    
      const increaseValueaAndAlertUpdatedValue = () => {
        const oldValue = value // Save old value before setValue() -- IMPORTANT!
        setValue((prev)=>{return prev + 1})
        alert(`updated value: ${oldValue + 1}`) // Use oldValue + 1 here
      }
    
      return (
        <div className='App'>
          <h1>Hello React TypeScript.</h1>
          <h2>Start editing to see some magic happen!</h2>
          <button onClick={increaseValueaAndAlertUpdatedValue}>increaseValueaAndAlertUpdatedValue</button>
        </div>
      );
    }
    

    BUT!!! Since you don’t use your value for rendering then much better solution in this case is to use useRef hook:

    import {useRef} from 'react';
    import "./styles.css";
    
    export default function App() {
      const value = useRef(0)
      const increaseValueaAndAlertUpdatedValue = () => {
        value.current++
        alert(`updated value: ${value.current}`)
      }
      return (
        <div className='App'>
          <h1>Hello React TypeScript.</h1>
          <h2>Start editing to see some magic happen!</h2>
          <button onClick={increaseValueaAndAlertUpdatedValue}>increaseValueaAndAlertUpdatedValue</button>
        </div>
      );
    }
    

    And yeah! You get stateless component, so no unnecessary rerenders when the counter is increased.

    You can read here about useRef().

    Login or Signup to reply.
  3. move the alert function outside of the component and pass in the updated value as a parameter to the function. This way, the value will be updated in the function and you can use it without waiting for the re-rendering to finish.

    const alertUpdatedValue = (value) => {
      alert(`updated value: ${value}`)
    }
    
    const increaseValueaAndAlertUpdatedValue = () => {
      setValue((prev)=>{return prev + 1})
      alertUpdatedValue(value)
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search