How to Migrate to v2 from v1
Changes in v2
React 19 officially introduces the use
hook to handle promises.
Valtio v1 internally handled promises, which is no longer recommended.
In Valtio v2, promises are not handled internally,
and developers should explicitly use the use
hook to manage promises.
Valtio v2 also introduces several changes in its design choices:
First, the behavior of proxy(obj)
has changed. In v1, it was a pure function and deeply copied obj
. In v2, it is an impure function and deeply modifies obj
. Generally, reusing obj
is not recommended, and if you have followed this convention, nothing will break.
Second, the behavior of useSnapshot()
has been altered. Although it is a subtle change, it is less optimized to ensure compatibility with useMemo
and the upcoming React compiler. The change may lead to extra re-renders in some edge cases, but it might not be noticeable.
Other notable changes to keep things updated and fresh include:
- Removal of all deprecated features
- Requirement of React version 18 and above
- Requirement of TypeScript version 4.5 and above
- The build target updated to ES2018
Migration for breaking changes
Resolving promises
// v1
import { proxy, useSnapshot } from 'valtio'
const state = proxy({ data: fetch(...).then((res) => res.json()) })
const Component = () => {
const snap = useSnapshot(state)
return <>{JSON.stringify(snap.data)}</>
}
// v2
import { use } from 'react'
import { proxy, useSnapshot } from 'valtio'
const state = proxy({ data: fetch(...).then((res) => res.json()) })
const Component = () => {
const snap = useSnapshot(state)
return <>{JSON.stringify(use(snap.data))}</>
// If `data` is not an object, you can directly embed it in JSX.
// return <>{snap.data}</>
}
Impure proxy(obj)
// v1
import { proxy } from 'valtio'
const state = proxy({ count: 1, obj: { text: 'hi' } })
state.obj = { text: 'hello' }
// v2
import { proxy } from 'valtio'
import { deepClone } from 'valtio/utils'
const state = proxy(deepClone({ count: 1, obj: { text: 'hi' } }))
state.obj = deepClone({ text: 'hello' })
Note that deepClone
is unnecessary unless you are reusing the object.
It is generally recommended to avoid reusing the object.