-
-
Notifications
You must be signed in to change notification settings - Fork 260
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
There is an useMutable"Snapshot" or useProxy? #283
Comments
what do you mean by to redirect all the set method? |
Sorry. I will try to be clear, useSnapshot is read-only. And I was wondering if there is another hook that returns a read/write state. Not to replace the useSnapshot, most of times immutability is needed, but in other situations directly write would be a nice to have. (or at least a hook that returns an unfrozen state) I have to say one more time, this library is awesome! |
A hook that if we try to write on the returned state, it should write on the relative path but on the proxy. |
This should work for most cases: const useMutableState = (proxyObject) => {
const [, forceUpdate] = useReducer((c) => c + 1, 0)
useEffect(() => subscribe(proxyObject, forceUpdate), [proxyObject])
return proxyObject
} The reason the library doesn't provide this is it's not perfect for concurrent react. supporting concurrent thing is my motivation to develop valtio from the beginning. it's not only for valtio, but for all my state libs. btw, have you seen the Found a related discussion: #38 const state = proxy({ count: 0 })
const Component = () => {
const snap = useMutableSnapshot(state)
const handleClick = () => {
snap.count++
snap.count++
// should count be 1 or 2?
}
...
} |
Any snapshot get/read access should reflect the immutable state as it was on the re-render time. In other hand, any set/write access should be "redirected" to the proxy. const handleClick = () => {
snap.count++
snap.count++
// should count be 1 or 2?
// snap.count=0 so should always be 1.
// for dependent write access we should still use the proxy directly.
} Assuming this two lines works behind the scenes in the same way: snap.count++
snap.count = snap.count + 1 For me this makes sense by the name of the hook (useMutableSnapshot), but this is completely theorical, I didn't see how Valtio works, and yes, now I understand the contraints. The hook useMutableState that you mentioned subscribes the entire proxy, so any change to the proxy will trigger a re-render, right? |
I don't want to add a new hook in valtio for this reason, and want the library to provide a single usage with That said, you are free to work on it on your end. And, I'm happy to help. See #38,
Exactly. |
Yes, makes sense. Thank you a lot for everything! One more time, you made a really impressive library! |
Closing this, but anyone can feel free to work on it. |
If anyone want a mutable and reactive state, you can try this. This may not be the best practice, but it workes. type DeriveGet = <T extends object>(proxyObject: T) => T
// you can read root state from context
const rootState = proxy({
num: 1
})
export const useReactive = <T extends object>(
target: (state: any) => T,
options: {
readonly?: boolean
} = {}
): T => {
const { readonly } = options
// you can read state from context
const value = target(rootState)
const [, forceUpdate] = useState([])
useEffect(() => {
let deriveFns
if (typeof value === 'object' && !Array.isArray(value)) {
deriveFns = {
...Object.keys(target(rootState)).reduce(
(prev: Record<string, any>, key: string) => ({
...prev,
[key]: (get: DeriveGet) => (target(get(rootState)) as any)[key]
}),
{}
)
}
} else {
deriveFns = {
obj: (get: DeriveGet) => target(get(rootState))
}
}
const derived = derive(deriveFns)
subscribe(derived, () => {
forceUpdate([])
})
}, [])
return readonly ? (snapshot(value) as any) : value
} usage function App() {
const state = useReactive((state) => state.num)
// do somthing
} |
The argument of useSnapshot is the proxy state, it is possible to 'redirect' all the set method to the proxy? The idea is to get a non frozen state, and be able to mutate directly, a dedicated hook for that.
The text was updated successfully, but these errors were encountered: