local-storage icon indicating copy to clipboard operation
local-storage copied to clipboard

Can't properly serialize digit strings (or other strings that happen to be valid JSON)

Open lynn opened this issue 3 years ago • 2 comments

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 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.

lynn avatar Feb 02 '22 22:02 lynn

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

jharrilim avatar Mar 25 '22 04:03 jharrilim

  • #76 Seems to be connected to this. as we are not converting the data on first load but only on subsequent calls.

iamsolankiamit avatar Apr 11 '22 19:04 iamsolankiamit