Closed jesstelford closed 3 years ago
Isn't it true that if you use useRecentPathsTracker()
at two places in your code the issue will appear without needing two tabs? This makes me think that the problem is not the syncing but that the useEffect()
updates the value every time it changes. Using setRecentPaths(recentPaths => {})
seems like a logical solution. Another way of fixing this problem is by making the useEffect()
run only on initial load by providing []
as a second parameter.
What I want to say is that it doesn't seem to be a problem with the syncing in particular but with the way you update the values.
Also, correct me if I am wrong but the first version of your code will create an infinite loop. The reason why it isn't blocking is that it uses useEffect()
. If you change it to useLayoutEffect()
it will hang your app.
I'm closing this issue for lack of activity.
@jesstelford If you have any more thoughts on this I will be happy to reopen this issue.
I wrote a custom hook to achieve tab independency* by only reading from local storage on mount, but still writing to it:
const useLocalStorageStateOnMount: typeof useLocalStorageState = (
key,
defaultValue?
) => {
const [inMemoryState, setInMemoryState] = useState(defaultValue);
const [storedState, setStoredState, props] = useLocalStorageState(
key,
defaultValue
);
useEffect(() => setInMemoryState(storedState), []);
const setState: typeof setInMemoryState = (value) => {
setInMemoryState(value);
setStoredState(value);
};
return [inMemoryState, setState, props];
};
*Of course that's not exactly session independency, it syncs on mount so navigation can still affect it, but it prevents tabs 'talking' to each other like the OP's issue.
@dalmo3, can you share what is your use case? Why do you want to opt out of cross tab syncing?
I have some tables that I can filter/sort and wanted to visualise them side-by-side with different filters on, while still saving the last state.
To be fair, given the caveat I mentioned about navigation, I still needed to handle unmounting so I ended up employing a mix of sessionStorage and localStorage, but that might digress too much from the original issue.
Thanks for the info.
Just a quick question about your use case. If you have two tables, do you bring both tables back when the user reopens the webpage? Because in this case you can assign ids for each table and keep both filters in localStorage. Just an idea.
Sorry, I wasn't clear. The side-by-side view was for the same table, with different filters applied.
How are they side-by-side and still be the same table? Do you have two windows opened side-by-side(split-screen) on the same page?
Yes, it's two tabs (that's the point of this whole thread)... How I organise the windows is irrelevant.
Yep, you are right. Sorry. I might have asked too many irrelevant questions. Your use case makes sense. I will think about it more. Thanks!
This library is fantastic, thank you!
I've come across a use-case where I need to opt-out of the cross-tab syncing, would it be possible to get a config option for this?
Here's the part I'm talking about:
https://github.com/astoilkov/use-local-storage-state/blob/master/src/useLocalStorageStateBase.ts#L80-L93
My use-case
I'm using
use-local-storage-state
to track recent URL paths visited.For example, I'll push each path onto an array such as:
['/about', '/blog', '/contact']
, etc.I then want to update the "Recent Path" on page load, so I do it in a
useEffect
:This works fine in a single tab, but when I open 2 tabs that point to different paths (for example;
example.com/blog
&example.com/about
), the following happens:example.com/blog
in Tab 1useEffect
callssetRecentPaths(['/blog'])
example.com/about
in Tab 2useEffect
setssetRecentPaths(['/about', '/blog'])
setRecentPaths
in Tab 2 updates the window's storage item, which triggers an event in Tab 1useEffect
sees a new value forrecentPaths
, so runs again and callssetRecentPaths(['/blog', '/about'])
setRecentPaths
in Tab 1 updates the window's storage item, which triggers an event in Tab 2useEffect
sees a new value forrecentPaths
, so runs again and callssetRecentPaths(['/about', '/blog'])
I don't actually need the cross-tab syncing for this usage, so would be happy with something like a
{ sync: false }
option:The workaround for now is to use the functional form of the
setRecentPaths
call:The end result is the
setRecentPaths
is only called once per mount, which is what I expected initially.