-
-
Notifications
You must be signed in to change notification settings - Fork 639
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
feat(core): unstable_createStore #922
Conversation
This pull request is being automatically deployed with Vercel (learn more). 🔍 Inspect: https://vercel.com/pmndrs/jotai/8URY6WAFLLJrn62GAdL94QAdtytL |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 99b7550:
|
Size Change: +721 B (+1%) Total Size: 98.1 kB
ℹ️ View Unchanged
|
src/core/store.ts
Outdated
const atomState = store[READ_ATOM](atom) | ||
return 'v' in atomState ? atomState.v : undefined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an unfortunate erasure if type Value = OtherThing | undefined
but the atom can also have a suspense promise. Perhaps the result of get
can be a more interesting type like { value: Value } | undefined
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And, what about the error case? Perhaps that should still throw, although I feel pretty strongly that store.get(atom)
should never throw the suspense promise.
If I have a const errorAtom = atom(() => throw new Error('oop'))
, then store.get(errorAtom)
should not return undefined
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is unfortunate.
I think it should throw on error, and maybe suspense too.
We could have has
method, hmm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does has
cause recompute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re: throwing promise: I think outside of React library authors it’s pretty unusual to think about throwing promises, whereas throwing errors is common for most JS styles. Given that the public store
intends to expose Jotai for use outside React, I think it might be inappropriate to throw the suspense promise since that’s a kind of react specific, framework internal practice. But I am behind the times in terms of React best practices so maybe this is better known in the cutting edge JS community?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the typescript perspective, you can't know if an atom will suspend or not.
Do we want to check type=value, even if we never use async in our code?
So, after all, if we were to explain it to someone who don't know suspense (which is likely), the original return undefined
idea would be easier (we throw on error). We would be simply explaining when the value is not ready, it returns undefined
. It's like how Map.get
is typed (but for a different reason).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, this: 4fd5afa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about a second method with the result type, for callers that are working with async and/or want the burden of checking the result for type safety? You had an option overload before, which is also fine too. I do think that returning undefined is better than throwing promise by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the public interface be expressive enough to allow an alternative implementation of useAtom by consumers, including suspense, if they chose to have those semantics? It’s not important to me, though. Another thought exercise about the purpose of the public store API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's the purpose of the RFC issue, to understand how people would use the public store API.
Exposing everything / having a second method would be all possible, but I don't think it's very good developer experience.
281a617 is reasonable in a sense that unstable_promise
is already introduced in getter in atom.write
. It's still very unstable though. Hm, it's too tricky for the public store API.
@dai-shi I'm wondering how to patch up my node_modules package with this PR ? notes after testing this:
|
@a-eid is the component reading the atom via store.get, or by useAtom? Store.get is non-reactive. I’ve been testing a similar change in my Jotai fork with a very similar implementation and it seems to be working fine — the only difference is in how the provider works. |
I used |
See: #922 (comment) Basically, find "Local Install Instructions" in: https://ci.codesandbox.io/status/pmndrs/jotai/pr/922
I haven't implemented this part yet. Will do shortly. |
@dai-shi what happens if you're getting an async storage atom on startup with the store. store.get("ASYNC_ATOM") |
@a-eid That's we had been discussing. Currently, it returns |
one use case that we can't get around is when running headlessJS task with react native. |
I'm not sure how would |
hm, not sure i get the real issue. we can consider
good point. we wouldn't be able to finalize the behavior very soon, but |
I think
currently to access an async atom outside react, we need to get it via |
If you "sub"scribe, you can "get" even the async value which is ready. I'm not sure if |
"sub"scribe would not work unless the atom is mounted. |
☝️
subscribe actually mounts the atom (and you need to unsubscribe to unmount it). |
As discussed in #861, this adds
unstable_createStore
api and prop. This is an experimental feature and may change without notices.