Search code examples
javascriptreactjsreact-nativeobservable

Using State Variable in Subscription and useEffect() in React for JavaScript


I am having a subscription, which I set up in the useEffect() Hook. Based on a variable from the store, I want to execute code (or not) which is also part of the body of the subscription.

const variableFromStore = useSelector(state => state.variableFromStore);
const dispatch = useDisptach();

useEffect(() => {
    const subscriptionEvent = SomeModule.AddSubscription(event => {
        console.log(variableFromStore);
        if(variableFromStore) {
            dispatch(foo());
        }
    });
})

Initially, variableFromStore is false. However, during interaction with the App (which includes unmounting the component, because the App is moved to background), it gets set to true. Then, some time later, subscriptionEvent gets fired.

But, when I console.log(variableFromStore)in there, it is always false, eventhough the redux debugger tells me it is true... Is it not possible to pass a state/store variable into a subscription?

I assume this is because I am setting up the subscription in the useEffect() hook, which only gets executed once. But, if I set it up like this

useEffect(() => {
    const subscriptionEvent = SomeModule.AddSubscription(event => {
        console.log(variableFromStore);
        if(variableFromStore) {
            dispatch(foo());
        }
    });
},[variableFromStore])

Wouldn't that reinitialize the subscription every time variableFromStore changes?


Solution

  • This happens because your useEffect callback runs only once, and the variableFromStore is enclosed by callback closure, to fix that, redux provides another way of getting the state from the store by calling the store getState method, which returns your whole state object, so you need to import your store first, from wherever it was created, and call getState method, this way the same last value will be returned as per using the selector, but that is not affected by closure:

    import store from '...'
    
    useEffect(() => {
        const subscriptionEvent = SomeModule.AddSubscription(event => {
            const { variableFromStore } = store.getState()
            console.log(variableFromStore);
            if(variableFromStore) {
                dispatch(foo());
            }
        });
    })