From 1d216a3eca32b10c75ee29ed5e99b6905f600807 Mon Sep 17 00:00:00 2001 From: Jenn Creighton Date: Wed, 3 Feb 2021 21:05:28 -0500 Subject: [PATCH 1/2] Recheck a variable's value in commit phase --- .../hooks/__tests__/useReactiveVar.test.tsx | 68 +++++++++++++++++++ src/react/hooks/useReactiveVar.ts | 10 +++ 2 files changed, 78 insertions(+) diff --git a/src/react/hooks/__tests__/useReactiveVar.test.tsx b/src/react/hooks/__tests__/useReactiveVar.test.tsx index 7c755d86d0e..20754b0da70 100644 --- a/src/react/hooks/__tests__/useReactiveVar.test.tsx +++ b/src/react/hooks/__tests__/useReactiveVar.test.tsx @@ -169,4 +169,72 @@ describe("useReactiveVar Hook", () => { console.error = error; }).then(resolve, reject); }); + + describe("useEffect", () => { + itAsync("works if updated higher in the component tree", async (resolve, reject) => { + const counterVar = makeVar(0); + + function ComponentOne() { + const count = useReactiveVar(counterVar); + + useEffect(() => { + counterVar(1); + }, []); + + return (
{count}
); + } + + function ComponentTwo() { + const count = useReactiveVar(counterVar); + + return (
{count}
); + } + + const { getAllByText } = render( + <> + + + + ); + + await wait(() => { + expect(getAllByText("1")).toHaveLength(2); + }); + + resolve(); + }); + + itAsync("works if updated lower in the component tree", async (resolve, reject) => { + const counterVar = makeVar(0); + + function ComponentOne() { + const count = useReactiveVar(counterVar); + + return (
{count}
); + } + + function ComponentTwo() { + const count = useReactiveVar(counterVar); + + useEffect(() => { + counterVar(1); + }, []); + + return (
{count}
); + } + + const { getAllByText } = render( + <> + + + + ); + + await wait(() => { + expect(getAllByText("1")).toHaveLength(2); + }); + + resolve(); + }); + }); }); diff --git a/src/react/hooks/useReactiveVar.ts b/src/react/hooks/useReactiveVar.ts index f348ac7bf14..a53af0750b5 100644 --- a/src/react/hooks/useReactiveVar.ts +++ b/src/react/hooks/useReactiveVar.ts @@ -18,5 +18,15 @@ export function useReactiveVar(rv: ReactiveVar): T { // const mute = rv.onNextChange(setValue); // return () => mute(); // }, [value]) + + // We check the variable's value in this useEffect and schedule an update if + // the value has changed. This check occurs once, on the initial render, to avoid + // a useEffect higher in the component tree changing a variable's value + // before the above useEffect can set the onNextChange handler. Note that React + // will not schedule an update if setState is called with the same value as before. + useEffect(() => { + setValue(rv()) + }, []); + return value; } From d976978f72a18e18258fbc8acc2f0e480846cc01 Mon Sep 17 00:00:00 2001 From: Jenn Creighton Date: Thu, 4 Feb 2021 17:23:24 -0500 Subject: [PATCH 2/2] Mention PR #7652 in CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aca382ebbe9..84aa51e3901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## Apollo Client 3.3.8 + +### Bug Fixes + +- Catch updates in `useReactiveVar` with an additional check.
+ [@jcreighton](https://github.com/jcreighton) in [#7652](https://github.com/apollographql/apollo-client/pull/7652) + ## Apollo Client 3.3.7 ### Bug Fixes