-1

I have declared a variable with usestate like as below

const [currentStepNumber, setCurrentStepNumber] = useState(0);

and then I am updating the state when I click on move function like as below

const handleMove = () => {
   setCurrentStepNumber(currentStepNumber + 1);
   const { label } = Object.values(PROJECT_PHASE).find(s => s.stepNumber === currentStepNumber);
   const projectPhaseID = projectPhaseData.projectPhases.find(a => a.name === label).id;
   console.log(currentStepNumber);
   // need to do API call as well in move function 
};

And the currentStepNumber still shows 0 instead of 1 only and i cannot use a timer to trigger and update the values. Is there any other approach to achieve this?

I need to update the currentStepNumber only in move function.

Glory Raj
  • 17,397
  • 27
  • 100
  • 203
  • Does this answer your question? [Why calling react setState method doesn't mutate the state immediately?](https://stackoverflow.com/questions/30782948/why-calling-react-setstate-method-doesnt-mutate-the-state-immediately) –  Jul 15 '20 at 21:42
  • No it won't i have to other operations as well after updating the state – Glory Raj Jul 15 '20 at 21:45
  • Doesn't matter; setting state is async; that's React 101 (also: the stupid "Does this answer your question?" is auto-inserted by SO when you mark as dupe) –  Jul 15 '20 at 21:50
  • 1
    Does this answer your question? [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – Drew Reese Jul 15 '20 at 21:50
  • @DrewReese That's the one, thanks –  Jul 15 '20 at 21:51
  • 1
    @ChrisG I've BM'd it since this question is asked almost daily. ;) Though, the underlying reason is exactly the same... react component lifecycle and reconciliation. – Drew Reese Jul 15 '20 at 21:51

2 Answers2

2

Might be able to try useEffect:

useEffect(() => {
   const postStepData = async () => {
     try {
         // call the api
         const response = await postDataPromise({...data, currentStepNumber});
         setCurrentStepNumber(0);
         setSomeOtherState(false);
     } catch (e) {
         console.log(e)
     }
   }

   const { label } = Object.values(PROJECT_PHASE).find(s => s.stepNumber === currentStepNumber);
   const projectPhaseID = projectPhaseData.projectPhases.find(a => a.name === label).id;
   console.log(currentStepNumber);
   /*
    * as an example only call api on step 4
   */
   if (currentStepNumber === 4) {
      void postStepData();
   }
}, [currentStepNumber])

const handleMove = () => setCurrentStepNumber(currentStepNumber + 1);

reference:

jmunsch
  • 22,771
  • 11
  • 93
  • 114
  • thanks for response !! , i need to have api call as well followed by getting that projectPhaseId in the same move function.. With your code can i do that – Glory Raj Jul 15 '20 at 21:36
  • Hmm i need to call the api in the current step it self cannot wait until step 4 – Glory Raj Jul 15 '20 at 21:46
  • @EnigmaState can remove the `if` statement, and just run the api call on each state update?, or handle the cases where it should be called? – jmunsch Jul 15 '20 at 21:48
  • do you mean the useEffect should run if there is any update to currentStepNumber right – Glory Raj Jul 15 '20 at 21:53
  • @EnigmaState yep – jmunsch Jul 15 '20 at 21:55
  • any condition need to check inside useEffect before running api call just to watch the current stepnumber or not needed – Glory Raj Jul 15 '20 at 21:56
  • @EnigmaState `currentStepNumber` is passed into the dependency array so the example useEffect will only run when `currentStepNumber` is updated. `useEffect(() => {...}, [currentStepNumber])`. If I understand your question, useEffect watches the current step number, and will run if it is updated, so no extra watching of step number is required for useEffect to get called. – jmunsch Jul 15 '20 at 22:06
  • thanks.. i need to run this complete useEffect when only the currentstepnumber changes and if don't include other dependencies i am getting warnings as well.. how can i avoid those warnings React Hook useEffect has missing dependencies: `projectPhaseData`. Either include them or remove the dependency array ` – Glory Raj Jul 15 '20 at 22:09
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/217922/discussion-between-enigma-state-and-jmunsch). – Glory Raj Jul 15 '20 at 22:19
0

You should use the new currentStepNumber in React's useEffect:

const MyComponent = () => {
  const [currentStepNumber, setCurrentStepNumber] = useState(0);
  
  const handleMove = () => {
    setCurrentStepNumber(currentStepNumber + 1);
  };

  useEffect(() => {
    const { label } = Object.values(PROJECT_PHASE).find(s => s.stepNumber === currentStepNumber);
    const projectPhaseID = projectPhaseData.projectPhases.find(a => a.name === label).id;
    console.log(currentStepNumber);
  }, [currentStepNumber])

  return (
    <>{/* some jsx */}</>
  )
}
Sheraff
  • 5,730
  • 3
  • 28
  • 53
  • thanks for the response, i have to do api call as well once i get the correct projectPhaseId in move function itself.. – Glory Raj Jul 15 '20 at 21:38