Skip to content

Commit 3eae4b2

Browse files
committed
Update refetch helper for useBackgroundQuery to use flushSync
1 parent e3e3014 commit 3eae4b2

2 files changed

Lines changed: 21 additions & 10 deletions

File tree

src/react/hooks/__tests__/useBackgroundQuery/customScalars.test.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,15 @@ test("preserves referential identity when refetching identical serialized scalar
294294
previousData = snapshot.data;
295295
}
296296

297-
void refetch();
297+
await expect(refetch()).resolves.toStrictEqualTyped({
298+
data: {
299+
event: {
300+
__typename: "Event",
301+
id: "1",
302+
startDate: new Date(2026, 0, 1),
303+
},
304+
},
305+
});
298306

299307
{
300308
const { renderedComponents } = await takeRender();

src/react/hooks/__tests__/useBackgroundQuery/testUtils.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import type { RenderOptions } from "@testing-library/react";
2-
import { screen } from "@testing-library/react";
32
import {
43
createRenderStream,
54
useTrackRenders,
65
} from "@testing-library/react-render-stream";
7-
import { userEvent } from "@testing-library/user-event";
86
import React, { Suspense } from "react";
7+
import { flushSync } from "react-dom";
98
import { ErrorBoundary } from "react-error-boundary";
109

1110
import type { DataState, ErrorLike, OperationVariables } from "@apollo/client";
@@ -47,24 +46,26 @@ export async function renderUseBackgroundQuery<
4746
return null;
4847
}
4948

49+
let currentRefetch!: useBackgroundQuery.Result<TData, TVariables>["refetch"];
50+
5051
function App({ props }: { props: Props | undefined }) {
5152
useTrackRenders({ name: "useBackgroundQuery" });
5253
const [queryRef, { refetch }] = renderHook(props as any);
5354

55+
currentRefetch = refetch;
56+
5457
return (
5558
<Suspense fallback={<SuspenseFallback />}>
5659
<ErrorBoundary
5760
FallbackComponent={ErrorFallback}
5861
onError={(error) => replaceSnapshot({ error })}
5962
>
6063
{queryRef && <UseReadQuery queryRef={queryRef} />}
61-
<button onClick={() => refetch()}>refetch</button>
6264
</ErrorBoundary>
6365
</Suspense>
6466
);
6567
}
6668

67-
const user = userEvent.setup();
6869
const { render, takeRender, replaceSnapshot } = createRenderStream<
6970
useReadQuery.Result<TData, TStates> | { error: ErrorLike }
7071
>();
@@ -75,11 +76,13 @@ export async function renderUseBackgroundQuery<
7576
return utils.rerender(<App props={props} />);
7677
}
7778

78-
// refetch needs to be run in an event handler in order for React 18 to commit
79-
// the suspense fallback
80-
async function refetch() {
81-
await user.click(screen.getByText("refetch"));
82-
}
79+
// React 18 skips committing the suspense fallback when refetch is triggered
80+
// as a default-priority update, so the fallback render is missed and tests
81+
// may fail. flushSync forces a synchronous commit so the fallback renders in
82+
// both React 18 and 19, while returning the refetch promise.
83+
const refetch: typeof currentRefetch = (...args) => {
84+
return flushSync(() => currentRefetch(...args));
85+
};
8386

8487
return { takeRender, rerender, refetch };
8588
}

0 commit comments

Comments
 (0)