joshnuss / svelte-persisted-store

A Svelte store that persists to localStorage

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Delete from storage when setting back to default value

PeppeL-G opened this issue · comments

Great package, many thanks!

Given GDPR, I shouldn't store data about the user when it's not needed (good practice even without GDPR). I have two questions about that when it comes to this package, hence this issue.


When I create a store like this:

const store = persisted('the-key', `the-default-value`)

Then nothing about this is stored in localStorage, right? It only gets stored in localStorage when I try to write a value to the store, right? Then this works preciously the way I want it to work, and I think it would be good to mention this in the docs (the README file).


When I change the value in the store back to it's default value, then in localStorage I can in my console see that the default value has been written there. That's a bit unnecessary (from GDPR and storage points of view), so I'm suggesting that when a value is written to the store, first check if that value is equal to the default value (after serialization), and if they are equal, then remove the key and the currently written value from the store, instead of storing the default value there.

You think this seems like a good idea that can be implemented?

Your point about not writing to localStorage upon initialization is correct. I do however not see the need (from a GDPR point of view) of removing the content from the store, as I would assume the default content isn't sensistive content of any kind?

Besides this, I don't think removing it from localStorage when setting back to default value directly would be a good idea, as this would require some (potentially pretty expensive) deep comparison whenever writing to the store. What we would could do would be to potentially add a seperate method for setting the store back to the default value and removing the localStorage content. Do however keep in mind that this is also something that can be achieved pretty easily client-side by using the localStorage api (except for some weird, undocumented behavior mentioned in #244 (comment))

Thanks for taking your time to discuss this!

If I remember right, my use-case was kind of that I wanted to keep track of if the user had accepted something (like accepting to store cookies/data on her computer). When the user accepts, I planned to remember this choice in localStorage. But I also wanted this to be reactive (so the GUI updates automatically in Svelte), so therefore I found and started to use this npm package.

So, I basically wanted a store that worked like this:

  1. const hasUserAccepted = persisted('hasUserAccpted', false)
    No problem creating the store like this when the SPA starts, since it doesn't store "false" on the user's computer
  2. Then when the user accepts, I use $hasUserAccepted = true. No problem storing true on the user's computer now, since the user has accepted
  3. Then, if/when the user takes back the permission to store data on her computer, it would be logical and convenient for me to simply write $hasUserAccepted = false, and the value in localStorage would have been deleted (i.e. we would be back on point (1) again)

You suggest adding a clear() method (or something named like that) that do what I want. Since I want to run $hasUserAccepted = false when the user clicks on a button, replacing that with hasUserAccepted.clear() works equally well for me, so I don't mind that solution.

A downside with that solution is that it wouldn't had worked if I instead would had used <input type="checkbox" bind:value={$hasUserAccepted}>. But in such a case I imagine one can simply add your own change listener instead of using bind, and then call clear() in the change listener, so maybe using clear() isn't such a bad solution after all :)

I concur that a clear() method makes more sense. Sometimes the defaults in the code change over time, but I want to retain the users actual selected choice. Harder to imagine that given the simple example above, but if you apply the same logic to things like website style choices it makes more sense.

My 2 cents: I think auto-clear on equality to the default value has a lot of impact in CPU for the few cases where it is needed: The code would always have to compare the value with the default value on every write request. I agree that a clear() method is probably a more sensible solution.

New idea: how about adding a storeDefault option when creating the store?

const preferences = persisted('local-storage-key', 'default-value', {
  storeDefault: true, // Set to false to clear the storage when the store is set to its default value.
})

Now, when storing a new value, a comparison is only needed when this value is false, so no extra computations are needed for those who don't want this functionality. But the name storeDefault = true sounds like it stores the default value in the storage as soon as the store is created, so maybe a better name is needed.

I'm happy with clear(), so for me it doesn't matter what we'll end up going with, just wanted to throw the idea out there.

Ok, a build-time preference sounds good. The implementation, however, must make sure the decision is only evaluated once during construction of the store and never again. Otherwise it would be changing one IF for a different IF. The way I would implement it would be using internal functions that have the code for the two versions, and then, on store build, decide which one to use. This would make the feature immutable after store creation.

My goal is always to keep this thing simple.

Adding options can make it harder for new users to learn. And I'm not sure this is an option that many users will use.

@PeppeL-G can't this be solved outside this library? For example, delete from local storage when user decides to revoke access?

An option is easier to learn than a method IMO, but I understand if you don't want to add any of them.

Sure, I can do it outside the library (that's what I'm doing at the moment, and it works), but then I would break your abstraction in my app, and maintaining my code base will be harder (e.g. if I for some reason would change from localStorage to sessionStorage in the future, just changing the storage option when creating the store is not enough, I would also need to find all the places where I have hackily added localStorage.removeItem('key') and change the store used there (that is, if I'm lucky enough to remember that I need to change them).

I'll of course accept whatever you choose to go with (there are good arguments both for adding and not adding).

I'd prefer that it is solved outside this library.

So I'll close the issue for now. But if others encounter a similar problem, please comment below and we can revisit this in the future.