Recoil: useRecoilCallback/set ignores previous sets made in a same batch

Created on 8 Jun 2020  路  1Comment  路  Source: facebookexperimental/Recoil

The useRecoilState properly applies multiple state updates made in one batch, just like original useState. On the other hand useRecoilCallback with set does not:

const $test = atomFamily({
  key: "test",
  default: { a: 0, b: 0 },
});

// ...

const [x, setX] = useState({ a: 0, b: 0 });
const [y, setY] = useRecoilState($test("xyz"));

const setYCB = useRecoilCallback(({ set }, n) => {
  set($test("xyz"), (x) => ({ ...x, c: n }));
}, []);

useEffect(() => {
  // update state multiple times with respect to previous update
  setX((x) => ({ ...x, a: 1 }));
  setX((x) => ({ ...x, b: 1 }));
  setY((x) => ({ ...x, a: 1 }));
  setY((x) => ({ ...x, b: 1 }));
  // this breaks the state, basically it ignores those 2 previous updates made
  setYCB(1);
}, []);

useEffect(() => {
  console.log("x", x);
  // ->聽{ a: 1, b: 1 }
}, [x]);

useEffect(() => {
  console.log("y", y);
  // ->聽{ a: 0, b: 0, c: 1 }, but expected result should be { a: 1, b: 1, c: 1 }
}, [y]);

From my point of view it seems like a bug.

bug

Most helpful comment

This was fixed with #260

useRecoilCallback() is now provided a snapshot of state which is consistent with the stable committed state at the start of the transaction. This would include the state before the effect started to execute. When it sets an atom with the updater form, the parameter providing the "previous value" is consistent with all previous state changes queued during the current transaction, this should include visibility on sets during the effect before the callback was executed.

Add unit test with #333

>All comments

This was fixed with #260

useRecoilCallback() is now provided a snapshot of state which is consistent with the stable committed state at the start of the transaction. This would include the state before the effect started to execute. When it sets an atom with the updater form, the parameter providing the "previous value" is consistent with all previous state changes queued during the current transaction, this should include visibility on sets during the effect before the callback was executed.

Add unit test with #333

Was this page helpful?
0 / 5 - 0 ratings