-
-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Throws when key is not in storage #1
Comments
Thanks for reporting this! I noticed this for the first time last week too when I cleared my cache. |
Hi @agilgur5 , sounds like a plan! Yes, setting the key to an empty object would work as long as the store is not initialized with some arbitrary state, in which case it would be re-hydrated with an empty object instead of keeping the original state. Of course the key could be set with that initial state instead of an empty object but seems redundant and appears to defeat the purpose of abstracting these details. I think the library following the above strategy would be a good default, but I'll leave that to your judgement :) Thanks for the quick response, Anton! |
Oh that's actually a good point, I didn't think about non-empty initial state. I'm not sure if Yea the solution here would then be not to set it to an empty object, but to just skip the |
Ok, seems like the Bookshop MST example also skips And this test shows that it falls back to the default of the model instead of the initial state when an empty object is applied. The source code (took a bit of digging) for the So yea, your point on initial state applies (nice catch!), and skipping the call would be best practice and a safe bet per the example. And yea the workaround right now would just be to set the storage key to the initial state if it doesn't exist until its implemented here. |
I've actually never used |
- if key is falsey, i.e. when storage has been cleared or has yet to be set to initial state, applySnapshot will fail and throw an error - so don't apply it if falsey, just skip the applySnapshot call - was thinking of applying `{}`, an empty object, if falsey, but this will reset the initial state of the store to its defaults - one might set initial state in `create({ ... })`, so that alternative doesn't work - getting the initial snapshot and setting it to itself was another alternative considered, but that would be quite complex with unnecessary operations, and might cause some unintended behavior due to whitelists, blacklists, etc applying - still need to think about the ramifications of those since applySnapshot doesn't merge, it just sets (and defaults are applied on top) - see also #1
Besides the considerations in the comment above and some missing tests, PR is out on #2. Can use the fix with |
Hi @agilgur5, sorry for the delay on this and thank you for taking the time to take a look on this so promptly! I am not sure on what you mean by "blacklisted initial attributes before anything is persisted will still exist". As far as I can see it, that would always be the case. Meaning, if I'm hydrating the store with some initial values, they should of course still exist, they just shouldn't be hydrated from permanent storage on future reloads -that is, they should always initialize to their initial If what you are saying is that when using
|
I think you understood correctly @rafamel . The problem with #2 is that no merging is ever performed in
These two states are very similar, but have different (potentially unintended) results. MST doesn't have a method to merge snapshots as far as I can tell, so it seems like this library might have to eventually implement something like I think I'll merge #2 for now as it resolves a critical bug, but will have to open another issue to resolve state merge strategies later. |
In that case I think what I was pointing out applies then? Assuming blacklisted/whitelisted keys are only for the store root object (so not nested), the logic for reconciling state should be fairly simple. Unless there's something I'm missing? return storage.getItem(name)
.then((data) => {
const snapshot = !jsonify ? data : JSON.parse(data)
applySnapshot(
store,
blacklist || whitelist ? Object.assign(store.toJSON(), snapshot) : snapshot
)
}) |
Yes, a shallow merge like you mentioned is an option. Whether or not it's simple isn't what I was referring to however -- a shallow merge is not necessarily the behavior a user wants or expects. MST doesn't define "merging" either, so we can't just delegate to MST for that behavior. I think #2, "'do nothing' if there is no persisted state" is the most intuitive option, but it may cause some gotchas without any merge strategies (it's critical enough that I think it should be pushed without them however). Shallow merge is the most intuitive default, but merge strategies should ideally be configurable and explicitly mentioned in the docs. Merge strategies are a separate issue, but are related in a few ways. |
- if key is falsey, i.e. when storage has been cleared or has yet to be set to initial state, applySnapshot will fail and throw an error - so don't apply it if falsey, just skip the applySnapshot call - was thinking of applying `{}`, an empty object, if falsey, but this will reset the initial state of the store to its defaults - one might set initial state in `create({ ... })`, so that alternative doesn't work - getting the initial snapshot and setting it to itself was another alternative considered, but that would be quite complex with unnecessary operations, and might cause some unintended behavior due to whitelists, blacklists, etc applying - still need to think about the ramifications of those since applySnapshot doesn't merge, it just sets (and defaults are applied on top) - see also #1
This comment has been minimized.
This comment has been minimized.
Hi @lucas-wilmart . Sorry, but what you're experiencing is different, I've added 100% test coverage since this issue was made, and it covers the case when no key is in storage multiple times.
Similar errors, but very different causes. This issue is an old bug around when nothing was in storage (an edge case as usually there's something in storage), not about whitelists etc.
Yea that's to be expected. This is the first issue and we covered a lot of ground here about related issues. The original title, description, and PR that fix it all still stand. What you're experiencing is related, hence the mention of #5 here, but not the same. I would probably suggest filing a separate issue if you're not sure/confused about something. Easier to close duplicates than redirect existing conversations.
Yep that is the topic of #5 . Please up-vote that if that is what you'd like.
Sorry, I'm inclined to mark this as off-topic as, other than being a different issue, putting a wholesale copy of a big portion of the codebase with only two lines added and many removed is bound to be even more confusing to any readers -- I'm the author and it was hard for even me to tell what changed. |
@agilgur5 Thanks a lot for your very detailed answer. I understand why you marked my answer as off-topic, sorry about that. I thought it could help people facing the same situation I did. |
Hi there, awesome work!
There's an issue, however, when the storage key doesn't exist. Of course, it can be catched, and then after the first save happens, it won't throw again for that key, but it might be sensible to check for the existence of a key in
storage
and, if it doesn't exist, save the initial value, if it exists, only then retrieve and hydrate.Otherwise we'll get ( w/
localforage
):The text was updated successfully, but these errors were encountered: