Storage hook `undefined` during initial render

Hey! I'm using the useStorage hook and noticed that during the initial render, it is undefined (default value) and then gets populated with the value from storage. I understand why this is the case (async data store vs sync rendering), however is there any way we can make it so that all storages are loaded before the rest of the application shows (i.e. no initial render with default values)?
35 Replies
lab
lab•2y ago
You can do value ? <Loading> : <ActualStuff>
nahtnam
nahtnam•2y ago
And chain them, fair enough. Lemme give that a shot! This is a bit trickier than I thought. useStorage('favoriteNumber', (value) => (value === undefined ? 10 : value));. Initially this will render (and persist) the value 10. If the user then modifies the value in the settings to 20 and opens up the extension again, they will see a flash of 10 before 20. And we can't really do a null check because theres a default value I suppose I could try useStorage('favoriteNumber') and useEffect where if(!favoriteNumber) setStorage(10) but I'm not sure if that would cause issues
lab
lab•2y ago
interesting maybe we can add something to the 3rd return value of the hook so the first 2 values model after useState the 3rd value provides more than that maybe we can add a isHydrated bool in the 3rd one and then only if the value is hydrated would we set that to true what do you think? bc useStorage tries to be an API-replica of useState, the concept of rehydration doesn't quite sync up (since useState hydration is supposedly synced with the runtime and renderer).
nahtnam
nahtnam•2y ago
Sorry just got back, that’s exactly the kind of solution I was thinking! I was toying around with suspense but couldn’t figure it out But that would also be an alternative cool solution Ah I’m too slow, I see you already implemented it Thank you! I’ll let you know if I find any problems
lab
lab•2y ago
oh yeah I actually just released it lol try out the latest version and lmk how it goes xD
nahtnam
nahtnam•2y ago
Is there a way to return this promise as well? https://github.com/PlasmoHQ/storage/blob/main/src/hook.ts#L61
GitHub
storage/hook.ts at main · PlasmoHQ/storage
💾 Safely store data and share it across your extension - storage/hook.ts at main · PlasmoHQ/storage
nahtnam
nahtnam•2y ago
I ask because I was messing around to see if I can implement suspense so I dont have to check for isHydrated in every location I use the store https://www.youtube.com/watch?v=PtoQpVOQ5Ew Seems like you need to throw a promise and react re-renders when the promise resolves
lab
lab•2y ago
PR welcome :p
nahtnam
nahtnam•2y ago
Let me try 🙂
lab
lab•2y ago
in term of is there a way, I wonder we can store that promise in a ref and expose it in the 3rd arg?
nahtnam
nahtnam•2y ago
I wonder if its as simple as passing suspense = true as a prop to the hook and then if (suspense) throw on that line Ah its in the useEffect, nvm
lab
lab•2y ago
I ask because I was messing around to see if I can implement suspense so I dont have to check for isHydrated in every location I use the store
One way to solve this is to use a context/provider
nahtnam
nahtnam•2y ago
Can I clone only the storage and link it or do I have to do the whole suite? Yeah but suspense is cooler 😛
lab
lab•2y ago
I wonder if it works with parcel tho since suspense is dynamic import and the current bundler atm is actually pretty shoddy at dynamic resolving atm, more so for extension since they usually expects a single bundle code (this is something we will need to improve along the line and think about - is there a way to do React server component/suspense in extension? <- this is a new frontier for next year imo) Even in NextJS, they had to make their own dynamic function to handle dynamic import since the default async import just sucks and doesn't work in their runtime/isomorphic so very likely Plasmo will have to adopt a similar strategy if it wanted to support suspense/dynamic import
Want results from more Discord servers?
Add your server