Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useEffect with callback not updating state

I'm trying to re-render a component to hide or show a 'Use current location' button when the user blocks or allows their location to be known (by clicking on the info icon to the left of the browser address in Chrome). I'm totally confused by why the first example below works, (ie. the button toggled appropriately as soon as the permission is changed) but the second doesn't (it requires a refresh).

I was attemping to remove the duplicate permission.state !== 'denied' by simply defining the constant hasPermission.

Also, I don't clean up the onchange listener. How do I do this? Can I just assign to null or delete the property?

Works:

    useEffect(() => {
        navigator.permissions.query({ name: 'geolocation' }).then(permission => {
            setHasPermission(permission.state !== 'denied')
            permission.onchange = () =>
                setHasPermission(permission.state !== 'denied')
        })
    }, [])

Doesn't work:

useEffect(() => {
    navigator.permissions.query({ name: 'geolocation' }).then(permission => {
        const hasPermission = permission.state !== 'denied';
        setHasPermission(hasPermission)
        permission.onchange = () => 
            setHasPermission(hasPermission)
    })
}, [])
like image 549
myleftshoe Avatar asked Mar 05 '26 12:03

myleftshoe


1 Answers

Basically, permission.onchange is defined only once.

So, when you define, in your second example, permission.onchange = () => setHasPermission(hasPermission) you create an event listener that will always call setHasPermission with the same value: the result of permission.state !== 'denied' saved above.

In your first example, it works because permission.state !== 'denied' is evaluated in the event callback.

Is it clear enough ?

For cleanup, useEffect can return a function that will be called when component unmounts. Please check https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1

like image 88
Pierre Ferry Avatar answered Mar 07 '26 01:03

Pierre Ferry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!