Valtio's current capabilities and what's possible in concurrent React #635
Replies: 4 comments 14 replies
-
"Key-based tracking" is highly related to "useSnapshot ref stability on child set", but I put them separately, because one might be feaible and the other not. It means that tracking proxy usage in render works with the following logic:
The current tracking works in a more complex and more unpredictable way:
This leads to 2 problems:
function Cmp() {
const store = useProxy(_store)
useEffect(() => {
fetch(api).then(response => store.slice1.data = response)
}, [store.slice1])
} Here, the linter mandates to put store.slice1 in the dep array, and the component will go into an infinite request loop. |
Beta Was this translation helpful? Give feedback.
-
@dai-shi , I recommend to your attention my newest version and findings. I think I tackled all the pain points:
Here is my new code: https://codesandbox.io/s/new-useexacttrackerproxy-xvfuu3?file=/src/useExactProxy.ts My thought process had a few corner points: (1) useRef can be used, only that it can't be accessed in render. But it's okay to mutate a render-closure variable, and pick the values from there in a useEffect (2) Concurrency support is mostly handled on a theoretical/speculative basis from library authors without actual tests to see how the lib behaves. See for example: reduxjs/react-redux#1860. The question in reduxjs/react-redux#1860 (reply in thread) is pretty much relevant and stays unanswered. There are reference and tearing effect tests at https://codesandbox.io/s/new-useexacttrackerproxy-xvfuu3?file=/src/useExactProxy.ts You can see that useExactProxy has better performance characteristics as well, compared to useSnapshot. There are also some tests at https://codesandbox.io/s/valtio-snapshot-unstable-reference-bug-forked-jmio2d?file=/src/CurrentUseSnapshot.tsx which I linked elsewhere earlier, showing how buggy useSnapshot is currently. My strategy was to implement an adequate tracking/scheduling logic, and use tearing tests to prove concurrency-compliance. As for tearing tests, I only found the one you showed in the react conf video (about mouse X), so I copied it and changed in a way that it involves proxy updates instead of mouse positions. The tearing tests quickly showed that only those implementations are prone to tearing problems, which don't have a proper scheduling logic. The mouse test was such. I made a vanilla proxy component, which obviously reproduced the tearing. useSnapshot didn't tear, but interestingly it showed an unwanted characteristics: it's super slow, because it goes through every step of the iteration (can't explain it better). I don't know if it's intended from your perspective, but it definitely doesn't reflect what startTransition is meant to be about. On the contrary, my new useExactProxy shows the desired characteristics: the costly renders are skipped, while the proxy updates and the useState call finish quickly. The logic has the following steps:
E.g., when a render has the following references: foo
foo.bar
foo.foo.bar.baz the following dependencies are collected:
And that's it. 2 acknowledgements:
In my mind, uSES is only relevant once it's the only thing which solves tearing. I'd love to see an actual test which demonstrates this. I could've added a set trap to the switch proxy to prevent in-render mutation, but I didn't even care about it. IMO it's not the lib's concern to prevent certain antipatterns. My goal was to have a mutation-based proxy syntax, which is predictibly tracked, performant, referentially stable and has no unforeseen underlying conflicts with idiomatic react usage. |
Beta Was this translation helpful? Give feedback.
-
Here's some comments on the table as of now.
useSnapshot should be stable, no?
What's this?
useSnapshot is actually stable for deep children, but usage tracking can break it. |
Beta Was this translation helpful? Give feedback.
-
It's surprisingly working well. It's different from my expectation with key-based tracking. It updates "text" correctly. There are extra re-renders, but it should be solvable. |
Beta Was this translation helpful? Give feedback.
-
This thread is opened to put on record all the features we encountered in the past days and evaluate them in the context of concurrency support. I'll update this table once something react-related comes up, and add comments below.
useWhatever(x) === useWhatever(x)
Beta Was this translation helpful? Give feedback.
All reactions