Search code examples
reactjsaxioscomponentsrenderinguse-state

How can I update state twice in a Parent component from a Child component?


I pass an "isLoadingToggle" to my Child component like so:

export function Parent() {

const [isLoading, setIsLoading] = useState(false)

function toggleIsLoading() {
  setIsLoading(!isLoading)
}

return ( <Child toggleIsLoading={toggleIsLoading} /> )

}

and the Child:

export function Child({ toggleIsLoading }) {

...

const toggle = useCallback(() => {
   // set the isLoading effect in the parent
   toggleIsLoading()

   axios.post(someUrl...)
   .then(response =>
      // do something with response
      // then tell the parent it's not loading anymore
      toggleIsLoading()
   }).catch(error => {
      // do something with error
      // then tell the parent it's not loading anymore
      toggleIsLoading()
   })
 }, []);

return ( <Button onClick={toggle}>Toggle isLoading in parent!</Button> )

Only the first isLoading state change is registered. The second call, after the axios post, is not.

How can I get isLoading to toggle in the parent whenever I call it?


Solution

  • It's a little bit tricky to explain what's happening here. anytime you mutate the state, the entire component re-renders. So when you get response and toggleIsLoading() is invoked. It doesn't really toggles the value of isLoading. It uses the old isLoading value from first render.

    What you can do is pass the boolean param to toggleIsLoading like this

    toggleIsLoading(true)
    toggleIsLoading(false)
    

    and define your function like this

    function toggleIsLoading(loading) {
      setIsLoading(loading)
    }
    

    Here is working demo https://stackblitz.com/edit/react-vgrkkf?file=src/Parent.js