From 4ad1967aec83809c7d03a3901f3a5499cfa3af4c Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Fri, 24 Mar 2023 10:51:09 +0000 Subject: [PATCH] fix(react-urql): Silence react render phase warning (#3095) --- .changeset/good-ads-watch.md | 5 +++++ packages/react-urql/src/hooks/state.ts | 21 +++++++++++++++++++ packages/react-urql/src/hooks/useMutation.ts | 6 +++--- packages/react-urql/src/hooks/useQuery.ts | 12 ++++++++--- .../react-urql/src/hooks/useSubscription.ts | 12 ++++++++--- 5 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 .changeset/good-ads-watch.md diff --git a/.changeset/good-ads-watch.md b/.changeset/good-ads-watch.md new file mode 100644 index 0000000000..fe89fda6fa --- /dev/null +++ b/.changeset/good-ads-watch.md @@ -0,0 +1,5 @@ +--- +'urql': patch +--- + +Silence "Cannot update a component (%s) while rendering a different component (%s)." warning forcefully. diff --git a/packages/react-urql/src/hooks/state.ts b/packages/react-urql/src/hooks/state.ts index 9ecb0bd924..c145b47748 100644 --- a/packages/react-urql/src/hooks/state.ts +++ b/packages/react-urql/src/hooks/state.ts @@ -1,3 +1,5 @@ +import * as React from 'react'; + export const initialState = { fetching: false, stale: false, @@ -41,3 +43,22 @@ export const hasDepsChanged = (a: T, b: T) => { for (let i = 0, l = b.length; i < l; i++) if (a[i] !== b[i]) return true; return false; }; + +const reactSharedInternals = (React as any) + .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + +export function deferDispatch>( + setState: Dispatch, + value: Dispatch extends React.Dispatch ? State : void +) { + if ( + process.env.NODE_ENV !== 'production' && + !!reactSharedInternals && + !!reactSharedInternals.ReactCurrentOwner && + !!reactSharedInternals.ReactCurrentOwner.current + ) { + Promise.resolve(value).then(setState); + } else { + setState(value); + } +} diff --git a/packages/react-urql/src/hooks/useMutation.ts b/packages/react-urql/src/hooks/useMutation.ts index 3e9e4ad72b..ad5ec0703e 100644 --- a/packages/react-urql/src/hooks/useMutation.ts +++ b/packages/react-urql/src/hooks/useMutation.ts @@ -13,7 +13,7 @@ import { } from '@urql/core'; import { useClient } from '../context'; -import { initialState } from './state'; +import { deferDispatch, initialState } from './state'; /** State of the last mutation executed by your {@link useMutation} hook. * @@ -155,7 +155,7 @@ export function useMutation< const executeMutation = useCallback( (variables: Variables, context?: Partial) => { - setState({ ...initialState, fetching: true }); + deferDispatch(setState, { ...initialState, fetching: true }); return pipe( client.executeMutation( @@ -165,7 +165,7 @@ export function useMutation< toPromise ).then(result => { if (isMounted.current) { - setState({ + deferDispatch(setState, { fetching: false, stale: !!result.stale, data: result.data, diff --git a/packages/react-urql/src/hooks/useQuery.ts b/packages/react-urql/src/hooks/useQuery.ts index 554ed5b740..d925abf5dc 100644 --- a/packages/react-urql/src/hooks/useQuery.ts +++ b/packages/react-urql/src/hooks/useQuery.ts @@ -17,7 +17,13 @@ import { import { useClient } from '../context'; import { useRequest } from './useRequest'; import { getCacheForClient } from './cache'; -import { initialState, computeNextState, hasDepsChanged } from './state'; + +import { + deferDispatch, + initialState, + computeNextState, + hasDepsChanged, +} from './state'; /** Input arguments for the {@link useQuery} hook. * @@ -317,7 +323,7 @@ export function useQuery< const updateResult = (result: Partial>) => { hasResult = true; - setState(state => { + deferDispatch(setState, state => { const nextResult = computeNextState(state[1], result); return state[1] !== nextResult ? [state[0], nextResult, state[2]] @@ -353,7 +359,7 @@ export function useQuery< ...opts, }; - setState(state => { + deferDispatch(setState, state => { const source = suspense ? pipe( client.executeQuery(request, context), diff --git a/packages/react-urql/src/hooks/useSubscription.ts b/packages/react-urql/src/hooks/useSubscription.ts index 33eadbcde0..85cc29385e 100644 --- a/packages/react-urql/src/hooks/useSubscription.ts +++ b/packages/react-urql/src/hooks/useSubscription.ts @@ -13,7 +13,13 @@ import { import { useClient } from '../context'; import { useRequest } from './useRequest'; -import { initialState, computeNextState, hasDepsChanged } from './state'; + +import { + deferDispatch, + initialState, + computeNextState, + hasDepsChanged, +} from './state'; /** Input arguments for the {@link useSubscription} hook. * @@ -257,7 +263,7 @@ export function useSubscription< const updateResult = ( result: Partial> ) => { - setState(state => { + deferDispatch(setState, state => { const nextResult = computeNextState(state[1], result); if (state[1] === nextResult) return state; if (handlerRef.current && state[1].data !== nextResult.data) { @@ -292,7 +298,7 @@ export function useSubscription< ...opts, }); - setState(state => [source, state[1], deps]); + deferDispatch(setState, state => [source, state[1], deps]); }, [client, args.context, request] );