sushinpv / react-secure-storage

This is a wrapper written above local storage to write the data securely to local storage
https://npmjs.com/package/react-secure-storage
MIT License
126 stars 12 forks source link

undefined gets saved as a string #39

Closed Mattijah closed 11 months ago

Mattijah commented 11 months ago

I am not sure what exactly causes this, but executing secureLocalStorage.setItem("test", undefined); then doing a website refresh and secureLocalStorage.getItem("test"); gets back "undefined". It should not be returning back a string as that is not what was saved.

sushinpv commented 11 months ago

Ideally you cannot set undefined to localStorage, it should throw error, We will patch the code to behave exactly like the default localStorage,

But if you are trying to remove a value which has been already set, then you should use removeItem(key), and when you tries to get a item which is not there on the localStorage, you will get null as a default response.

Mattijah commented 11 months ago

Why should it throw an error? Just replace the value with undefined the same way localStorage works. Sometimes it happens that the value provided whatever that is might not be available and hence undefined

sushinpv commented 11 months ago

I would like to clarify that what I was referring to is the default behavior of localStorage. When you use localStorage.setItem("test", undefined), it will indeed store an "undefined" string in the local storage. Consequently, when you retrieve the value, it will be returned as a string.

For visual reference, please consult the screenshot below: This is a reference from Google Chrome

Screenshot

There are a few possible approaches we can consider:

  1. Maintain the Default Behavior: Retain the current behavior, as it aligns with the default behavior of localStorage.

  2. Library-Based Conversion: Implement a mechanism within the library to automatically convert the stored "undefined" string back to the actual undefined value when retrieved.

  3. Throw an Error: Consider throwing an error in cases where "undefined" is attempted to be saved. This can signal that the property is not yet defined, and it should not allow the storage of an undefined value.

  4. Remove Existing Values: When a user attempts to set "undefined" for an existing key, we could remove the existing value associated with that key.

Mattijah commented 11 months ago

Ah, I see. I actually did test it with localStorage, but it returned undefined maybe I did something wrong. I guess in this cases makes sense to align with the default behaviour although with the secureStorage I also noticed that if I set let's say a number 123 it returns that number and not a String, so that already misaligns then (unless I did something wrong)

sushinpv commented 11 months ago

In the default implementation of localStorage, it's important to note that both the key and the value need to be in string format. You can find further reference on this behavior in the following screenshot:

Screenshot

You can also refer to the official documentation here: Mozilla Developer Network - Window.localStorage.

As per the documentation:

The keys and values stored with localStorage are always in the UTF-16 string format, which uses two bytes per character. Integer keys are automatically converted to strings, similar to how objects are handled.

Typically, when you intend to set a value other than a string, you'll either need to explicitly convert it to a string or rely on the default conversion to a string.

However, this can pose a challenge for many developers, particularly when they often need to store JSON objects, as illustrated in the example below:

localStorage.setItem("test", JSON.stringify({
    test: "testing",
}))

let data = localStorage.getItem("test");    
if(data) data = JSON.parse(data);

In such cases, developers need to constantly check if the data exists before attempting to convert it to JSON. If the data is corrupted or cannot be converted back to JSON, it may result in runtime errors. Consequently, this often necessitates the addition of try/catch blocks to handle these potential errors in all read statements.

This is why react-secure-storage has been designed to preserve the datatype of the data being set. If you desire the default behavior of localStorage, you can explicitly convert all your data to strings.

We have clearly defined this in our library's description, which you can review here: React Secure Storage - Why React Secure Storage.

screenshot:

Screenshot 2023-11-09 at 9 48 30 AM

Additionally, addressing your specific question, when you attempt to set undefined to the secureLocalStorage, we have chosen to remove the existing key from the secureLocalStorage. This decision aligns with the same behavior that occurs when a key is not present in the secureLocalStorage; by default, it returns null. This approach ensures consistent behavior and simplifies error handling.

Furthermore, you can expect this patch to be included in the next release.

sushinpv commented 11 months ago

This issue has been patch on our latest version of the app react-secure-storage@1.3.2

DXN5 commented 7 months ago

Cell phone operation. Data in localStorage was filled via secureLocalStorage. When you switch to the PC version in the browser, the values with keys are deleted... If you work with regular localStorage, there is no such problem when switching. Does anyone know the solution to the problem ?