local-storage
local-storage copied to clipboard
Can't properly serialize digit strings (or other strings that happen to be valid JSON)
When I write
const [x, setX] = useLocalStorage<string>("test", "");
useEffect(() => setX("123456789123456789123"));
console.log("x =", x);
I see x = 123456789123456800000
after refreshing the page.
This is because the value is identified as being JSON when reading it back out of LocalStorage, and then JSON.parse
turns it into a float, with loss of precision.
In fact, x
is now indeed a number
, even though the type signature of useLocalStorage
promises that it is string
. :scream:
Always converting JSON has other weird consequences:
- You can type something like
{"wow": "json injection"}
into a useLocalStorage-backed text field and break stuff! - When serializing the word
"true"
, it comes back out as a boolean valuetrue
. - …
It might be nice to have a useLocalStorageRaw
that only works with strings and does not "helpfully" parse strings as JSON whenever it has the opportunity.
That is a really good point. It seems to come from this line:
https://github.com/rehooks/local-storage/blob/db301e64d3db82f75775bdb477ca42feb5e3e49b/src/local-storage-events.ts#L67
I don't remember why this was done truthfully, but if we just did JSON.stringify
on all values, it would avoid this problem
- #76 Seems to be connected to this. as we are not converting the data on first load but only on subsequent calls.