astoilkov / use-local-storage-state

React hook that persists data in localStorage
MIT License
1.1k stars 41 forks source link

Persist in localStorage, but do not upgrade React state #46

Closed rwieruch closed 2 years ago

rwieruch commented 2 years ago

Hi @astoilkov thanks for this great library.

I ran into an edge case and was wondering if that's a feature you may wanna support in the future:

In my case, I want to call setValue for storing the value in local storage, but without updating React's state. In other words, when calling setValue, I do not want a state update and thus no re-render. Scenario: I only want to use useLocalStorageState to write to the local storage and to pick up the value from the storage for the initial rendering, in between I do not care about the value anymore.

This could probably be solved with another property in the options object, e.g. { onlyWrite: true } which would prevent the internal setState call. However, I can also understand if that's something the library is no supposed to offer, because it's after all a solution for syncing the local storage to React's state.

rwieruch commented 2 years ago

My workaround at the moment:

const [resizedLayout] = useLocalStorage('table-widths', {
  defaultValue: [],
});

// we do not want a re-render 
// but only remember the table's columns widths
// to apply when the table gets rendered from scratch
// https://github.com/astoilkov/use-local-storage-state/issues/46
const setResizedLayout = (widths) => {
  if (localStorage) {
    localStorage.setItem('table-widths', JSON.stringify(widths));
  }
};
astoilkov commented 2 years ago

I understand your scenario. Give me some time to think about this. I've seen people wanting to get the state only initially and then don't update it but I should think if there is a unifying solution that can fit all scenarios.

astoilkov commented 2 years ago

Is this solution going to work for you:

const [resizedLayout, setResizedLayout] = useLocalStorage('table-widths', {
  defaultValue: [],
});
// in the code you always use `initialResizedLayout` and you can now call `setResizedLayout()` without causing your behavior to break
const initialResizedLayout = useRef(resizedLayout).current

As my users have written about the same problem I'm thinking of updating the readme. If this solution works for you I would think about explaining this scenario. The solution seems simple and elegant.

astoilkov commented 2 years ago

Hey @rwieruch. Just a reminder. Did you have time to see what I'm proposing?

astoilkov commented 2 years ago

I'm closing this because of a lack of activity.