Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

old state is rendering after browser refresh #139

Closed
ghost opened this issue Nov 4, 2022 · 9 comments
Closed

old state is rendering after browser refresh #139

ghost opened this issue Nov 4, 2022 · 9 comments

Comments

@ghost
Copy link

ghost commented Nov 4, 2022

Hi
I'm getting wrong state after the browser is refreshed
I've set the persist to true and stored the state to localStorage
I'm attaching the stackblitz source code can you please check the source code and tell me what i'm doing wrong ?
https://stackblitz.com/edit/react-ts-gtkmpa?file=Tabs.jsx
I've multiple states that need to be stored globally and locally
I've tried the examples also but i couldn't figure out what is wrong

@yezyilomo
Copy link
Owner

Thank you for reporting this.
It seems like there's a bug in persisting states, I'm working on it.

@ghost
Copy link
Author

ghost commented Nov 6, 2022

Hi I've tried the new version
But i'm still getting the error should i change the source code I've just updated the package
and tried it
https://stackblitz.com/edit/react-ts-kknj8r

@yezyilomo
Copy link
Owner

yezyilomo commented Nov 6, 2022

The issue is on debouncing state saving, a good way to dounce state saving should be like

import { createStore } from 'state-pool';

const store = createStore();


// ===================================================
// Use this if you want to allow store persistance in local storage

function debounce(func, timeout = 1000) {
    let timer;
    return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => { func.apply(this, args); }, timeout);
    };
}

store.persist({
    PERSIST_ENTIRE_STORE: true,  // Use this only if you want to persist the entire store
    saveState: function (key, value, isInitialSet) {
        
        const doStateSaving = () => {
            try {
                const serializedState = JSON.stringify(value);
                window.localStorage.setItem(key, serializedState);
            } catch {
                // Ignore write errors
            }
        }

        if (isInitialSet) {
            // We don't debounce saving state since it's the initial set
            // so it's called only once and we need our storage to be updated
            // right away
            doStateSaving();
        }
        else {
            // Here we debounce saving state because it's the update and this function
            // is called every time the store state changes. However, it should not
            // be called too often because it triggers the expensive `JSON.stringify` operation.
            const DEBOUNCE_TIME = 1000 // In milliseconds
             // Debounce doStateSaving before calling it
            const processStateSaving = debounce(doStateSaving, DEBOUNCE_TIME);
            processStateSaving()  // save State
        }
    },
    loadState: function (key, noState) {
        try {
            const serializedState = window.localStorage.getItem(key);
            if (serializedState === null) {
                // No state saved
                return noState;
            }
            return JSON.parse(serializedState);
        } catch (err) {
            // Failed to load state
            return undefined
        }
    },
    removeState: function (key) {
        window.localStorage.removeItem(key);
    },
    clear: function () {
        window.localStorage.clear();
    }
})
// ===================================================


export default store;

That's how your store.js file should be

@ghost
Copy link
Author

ghost commented Nov 6, 2022

Thanks I got it working now
But i'm confused what is wrong
All I understood is setTimeout and clearTimeout has been refactored to debounce

I can't understand any difference between the two
and why do we need to wait 1000 milli seconds before saving the state?
I thought debounce is used for avoiding unnecessary calls like every letter typed or some repeated api calls

@yezyilomo
Copy link
Owner

Debouncing is just for optimization, it's not a must you can actually remove it and it would work just fine, the time too is not fixed(1000) you can use any value which suits you. The reason for debouncing is because when saving state in doStateSaving we're using JSON.stringify to serialize our state in order to save them, now this is an expensive operation it shouldn't be called very often especially if you have a lot of state to save so deboucing is one way to reduce calling that operation.

@ghost
Copy link
Author

ghost commented Nov 6, 2022

Thanks for the explanation

@yezyilomo
Copy link
Owner

There was a bug in debouncing that's why it was skipping saving some states, so refactoring it removed that bug that's why it's working fine now.

And in your example at https://stackblitz.com/edit/react-ts-kknj8r you don't need to pass {persist: true} anywhere if you have already set PERSIST_ENTIRE_STORE: true, this setting will activate persisting all states in a store by default unless you pass {persist: false} when setting a state in your store.

@yezyilomo
Copy link
Owner

Thanks for the explanation

Thank you for reporting this too, I will update examples for persisting state on documentation to avoid that bug on debouncing

@ghost
Copy link
Author

ghost commented Nov 6, 2022

okay now I understand what was the bug and yeah i will not pass {persist: true}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant