-
-
Notifications
You must be signed in to change notification settings - Fork 40
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
Async storage lookup/default value issue #43
Comments
I think your case will be fixed when 762fe4f lands in v16. I will write here when that happens so you can test it. How does that sound? |
@astoilkov: That seems to be exactly what I want! I install directly from |
@astoilkov:
|
I will soon make a new release. I will write you then so you can try with it. |
@astoilkov: Ah, that would be great! I was just diving into the |
Done. Can you try out the new v16 release? |
@astoilkov: Alright, I installed |
Can you share your code? Or at least a snippet of the important stuff so I can get a better understanding of what's happening. Note that it will render twice but the code will call |
Sure! import {
useCallback,
} from 'react'
import useLocalStorageState from 'use-local-storage-state';
const tableIdParamName = 'seat';
const localStorageSeatKey = 'seat';
export default function SeatProvider({ children }: { children: any }) {
// persist (query is discarded by router)
const [seatId, setSeatId, { removeItem: removeSeatId, isPersistent: isSeatIdPersistent }] =
useLocalStorageState<number>(localStorageSeatKey, {
ssr: true,
defaultValue: -1, // -1 = no seat set
});
// initial seatId - use when set
const url: URL = new URL(window.location.href);
const params: URLSearchParams = url.searchParams;
const initialSeatIdVal = params.get(tableIdParamName);
if (initialSeatIdVal !== null) {
const initialSeatId = parseInt(initialSeatIdVal);
setSeatId(initialSeatId);
}
useCallback(() => {
// This is called in 1st render, regardless of what is stored:
if (seatId === -1) {
throw new Error('No seat was assigned.');
}
}, [seatId]);
// [...]
} |
Hmm. I can't seem to replicate the issue. Here is the CodeSandbox I've experimented with: https://codesandbox.io/s/todos-example-use-local-storage-state-forked-s03chx?file=/src/App.tsx. Can you modify it in order to replicate the problem? |
@astoilkov: Thanks for your help! So I forked and modified your example a bit so the issue occurs (as in the app): |
You modified the example in a way where the If you place |
@astoilkov: This may explain the issue: I have a misunderstanding of how const [value, setValue] = useLocalStorageState("value", {
ssr: true,
defaultValue: -1
});
console.log(value);
if (value === -1) {
setValue(22);
} So instead of using |
I should appologize as I didn't see the problem because it happens only on the first render after the |
@astoilkov: The issue still persists 😿 . Default value in first render and set value in subsequent renders. |
Ok. I think I know what is happening so I will chronologically explain what happened until now. in version 15.0.0In this version two bugs exist:
in version 16.0.0The 1. bug was fixed. in version 16.0.1The 2. bug was fixed. ConclusionThe confusing part was that I thought your code will get fixed when I make the fixes (not sure if it did). However, you are right that there are two renders. Let me explain why. When |
@astoilkov: Thanks! One question: When |
You can read more here: https://reactjs.org/docs/react-dom.html#hydrate. Conclusion is — you can avoid it by setting the |
@astoilkov: With |
Cool. If that works for you and you don't have issues with hydration mismatches then this is a great solution. |
@astoilkov: A React app can have a query parameter (e.g.
?appId=123
) which is persisted using thisuse-local-storage-state
hook.A default value is also set (
-1
). When the state is-1
, an error is thrown (no App ID is set, the app needs an App ID to function).The problem is that the
use-local-storage-state
is asynchronous: In the first render the value is still the default value (-1
), in the 2nd render the value is the one retrieved from local storage.This means that in the first render the app already shows an error message, as the error will also stop further renders.
How can I get around this?
The text was updated successfully, but these errors were encountered: