Recoil
Recoil copied to clipboard
Effect `onSet` doesn't run when resetting atoms
Resetting atoms either with useResetRecoilState
or reset
inside a useRecoilCallback
does NOT trigger onSet
event in the atom effect.
const state = atom<string>({
key: "state",
effects: [
(it) => {
if (it.trigger === "get") it.setSelf("state");
it.onSet((newValue, oldValue, isReset) =>
console.log({ newValue, oldValue, isReset })
);
},
],
});
function Test() {
const value = useRecoilValue(state);
return <>{value}</>
}
function Component() {
const resetState = useResetRecoilState(state);
useEffect(() => {
const timeout = window.setTimeout(() => resetState(), 1000);
return () => window.clearTimeout(timeout);
}, [resetState]);
return (
<Suspense fallback="Loading">
<Test />
</Suspense>
);
}
In the example above, it console.log does NOT run when resetState
is called (1 second after mount).
onSet
fires when the newValue is different from the old one. Try set it to a different value before you reset
Also a few nits in your code:
function Test() {
const value = useRecoilState(state);
return <>{value}</>
}
This looks problematic. You probably want to use useRecoilValue
if (it.trigger === "get") it.setSelf("state");
It's weird you want to set the atom value when reading. Maybe use default
?
Hope these help
I use setter because the atom is designed not to have default value so that when I reset it, it will be put back to pending state, instead of default value.
In the example, newValue
is a reset, when oldValue
is "state"
right?
Ah, you are right.
I took a look at the implementation. Looks like onSet
will only execute when it gets actual contents of the new value. https://github.com/facebookexperimental/Recoil/blob/37ca477b8b4b6d56432a164470672da0868396e7/packages/recoil/recoil_values/Recoil_atom.js#L406
In this case, the default value is in a pending state, so onSet
handler won't run.
@drarmstr do you consider this as working as intended?
Is there any status on this, guys? 🤔