async
Promises
Promises may be values in a proxied object. They will be resolved in calls to snapshot
.
// vanillajs example
const countDiv: HTMLElement | null = document.getElementById('count')
if (countDiv) countDiv.innerText = '0'
const store = proxy({
count: new Promise((r) => setTimeout(() => r(1), 1000)),
})
subscribe(store, () => {
const value = snapshot(store).count
if (countDiv && typeof value === 'number') {
countDiv.innerText = String(value)
store.count = new Promise((r) => setTimeout(() => r(value + 1), 1000))
}
})
Suspend your React components
Valtio is compatible with React 19 use
hook. This eliminates all the async back-and-forth, you can access your data directly while the parent is responsible for fallback state and error handling.
import { use } from 'react' // React 19
// import { use } from 'react18-use' // React 18
const state = proxy({ post: fetch(url).then((res) => res.json()) })
function Post() {
const snap = useSnapshot(state)
return <div>{use(snap.post).title}</div>
}
function App() {
return (
<Suspense fallback="Loading...">
<Post />
</Suspense>
)
}
It still suffers from "de-opt", which prevents useTransition
to work well. To mitigate it, there is a third-party library use-valtio.