-
Notifications
You must be signed in to change notification settings - Fork 4
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
Does this allow async computed atoms like jotai does? #2
Comments
Hi Peter, Short answer: nope, not yet. Long answer: It's interesting to think about how we would go about doing this. In jotai's case, what they do is for derived atoms, they use suspense, so the suspense boundary renders the placeholder (loading, spinner, etc) while the atom has no value. Klyva exists outside of react, so it has no concept of suspense. Also, in Klyva, so far, all atoms always have a value, for async functions, this would not be the case. So how would we model this in klyva? One suggestion would be, that if the atom is async, the atom returns a union value, where the value can be in different states: I can make a PR for this. What we could then do, in the future, is that if |
Hi Meris, Thanks for the quick reply. The union value makes sense. I was trying to figure out a way to do that (was thinking of finding if it was a function and throwing the promise). The idea that the atom can be updated outside the react ecosystem is actually a very common use case in UI. const atomOne = atom(10)
const atomTwo = atom(20)
const sumAtom = atom((get) => get(atomOne) + get(atomTwo))
function App() {
const d = useAtom(atomOne)
const g = useAtom(sumAtom)
return (
<div className="App">
{d}
{'-'}
{g}
</div>
);
} Error:
|
Hi, first of all, thanks for the report, it has been fixed here: 2ccdc97
Yes, it feels like such a normal case, and this optimizes for that. |
Thanks it works now. import React from 'react'
import { ReadOnlyAtom } from './types'
const promiseCache = new Map<any, any>()
export const useAtom = <T>(atom: ReadOnlyAtom<T>) => {
const [cache, setCache] = React.useState(atom.getValue())
React.useEffect(() => {
const unsub = atom.subscribe(value => {
promiseCache.delete(cache);
setCache(value)
})
return unsub
}, [atom, cache])
if (cache instanceof Promise) {
const v = promiseCache.get(cache)
if (v) {
if (v instanceof Error) {
throw v
} else {
return promiseCache.get(cache)
}
}
cache
.then((res) => {
promiseCache.set(cache, res)
})
.catch((err) => {
promiseCache.set(cache, err)
});
throw cache
}
return cache
} import React, { Suspense } from 'react';
import ReactDOM from 'react-dom';
import { atom } from 'klyva'
import { useAtom } from './utils';
const atomOne = atom(1)
const atomTwo = atom(10)
const sumAtom = atom((get) => get(atomOne) + get(atomTwo))
type Todo = {
complete: Boolean
title: String
}
const todoAtom = atom<Promise<Todo>>(async (get) => {
const one = get(atomOne)
const res = await fetch("https://jsonplaceholder.typicode.com/todos/" + one);
return await res.json()
})
function App() {
const a = useAtom(atomOne)
const sum = useAtom(sumAtom)
const todo = useAtom(todoAtom)
return (
<div className="App" onClick={() => atomOne.update((v) => v + 1)}>
{a}
{'-'}
{sum}
{'-'}
{todo.title}
</div>
);
}
ReactDOM.render(
<React.StrictMode>
<Suspense fallback={<div>loading...</div>}>
<App />
</Suspense>
</React.StrictMode>,
document.getElementById('root')
); |
I would like to try doing something like this,
The text was updated successfully, but these errors were encountered: