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?
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