Question: when does selector re-compute
See original GitHub issueImagine I have bunch of atoms:(all numbers)
const a = atom(...);
const b = atom(...);
const c = atom(...);
and a selector like below:
const s = selector({
key: uniqueKey,
get: ({get}) => {
cobst aVal = get(a);
const bVal = get(a);
const cVal = get(a);
return aVal+bVal+cVal;
}
});
Now if on click of a button we call the following:
const clickHandler1 = useRecoilCallback(({set}) => () => {
set(a, 1);
set(b, 1);
set(c, 1);
});
vs.
const clickHandler2 = useRecoilCallback(({set}) => async () => {
set(a, 1);
set(b, 1);
--- await an asyc call here ---
set(c, 1);
});
How many times the selector s gets recomputed. Does the useRecoilCallback act as transaction? If not, how can one make updates to atoms transactional.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:5 (3 by maintainers)
Top Results From Across the Web
Reselect selector keeps recomputing with the same input
Selectors created with createSelector have a cache size of 1. This means they always recalculate when the value of an input-selector changes, as ......
Read more >Common Reselect Gotchas | Blog
Any time an action is dispatched that doesn't change state.todos we won't have to recompute the list of sorted todos, and that is...
Read more >Understanding Javascript Selectors With and Without ...
category === 'pants' . This is a problem because Reselect selectors have a cache size of 1, which means that in this case...
Read more >Redux Selectors: A Quick Tutorial
A selector is a small function you write that can take the entire Redux state, and pick out a value from it. You...
Read more >Performant Redux Selectors with Reselect
Selectors created using Reselect's createSelector function are memoized. That's a fancy word to mean that the function remembers the arguments ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
As @mondaychen indicated,
useRecoilCallback()
is intended for the synchronous execution to act as a transaction and will modify the Recoil state atomically and attempt to batch the updates for a single React render. With theawait
it will simply resume execution when the await resolves or throw if it rejects for a new transaction. You should not see a selector evaluation wherea
was set andb
was not. (File a bug if you do 😉However, that said, the selector could still be executed multiple times if any of the dependencies are themselves async. If those dependencies are still pending when it attempts to re-evaluate, then it will abort execution and retry again from the beginning when that dependency resolves or rejects. This follows the same semantics as React Suspense. In general, there is a contract that selector evaluation functions are idempotent and have no side-effects (other than caching, logging, and similar exceptions 😉 The selector evaluation may also be cached and/or the cache may be invalidated. You should not make any assumptions as to how many times a selector is evaluated.
Thanks for the explanation @drarmstr @mondaychen I did observe the behavior via
console.log
, it was weird to see that for updates viaset(atom, callback)
it batches the updates but when there is an async call it doesn’t, so I asked the quesiton. I’m coming from a mobx background and I was expecting a utiltransaction
function to manually batch operations (sync and async). Without it, a selector such as above will need lots of checking to prevent throwing due to undefined/null/etc. values for dependencies.