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. 😱
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 value true.
- …
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.
When I write
I see
x = 123456789123456800000after refreshing the page.This is because the value is identified as being JSON when reading it back out of LocalStorage, and then
JSON.parseturns it into a float, with loss of precision.In fact,
xis now indeed anumber, even though the type signature ofuseLocalStoragepromises that it isstring. 😱Always converting JSON has other weird consequences:
{"wow": "json injection"}into a useLocalStorage-backed text field and break stuff!"true", it comes back out as a boolean valuetrue.It might be nice to have a
useLocalStorageRawthat only works with strings and does not "helpfully" parse strings as JSON whenever it has the opportunity.