Recoil icon indicating copy to clipboard operation
Recoil copied to clipboard

Effect `onSet` doesn't run when resetting atoms

Open phuctm97 opened this issue 2 years ago • 4 comments

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).

phuctm97 avatar Feb 21 '23 13:02 phuctm97

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

mondaychen avatar Feb 21 '23 20:02 mondaychen

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?

phuctm97 avatar Feb 22 '23 05:02 phuctm97

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?

mondaychen avatar Feb 23 '23 18:02 mondaychen

Is there any status on this, guys? 🤔

mister-teddy avatar Mar 11 '24 09:03 mister-teddy