Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

fix(react-urql): Silence react render phase warning (#3095)

Changed files
+47 -9
.changeset
packages
+5
.changeset/good-ads-watch.md
···
+
---
+
'urql': patch
+
---
+
+
Silence "Cannot update a component (%s) while rendering a different component (%s)." warning forcefully.
+21
packages/react-urql/src/hooks/state.ts
···
+
import * as React from 'react';
+
export const initialState = {
fetching: false,
stale: false,
···
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<Dispatch extends React.Dispatch<any>>(
+
setState: Dispatch,
+
value: Dispatch extends React.Dispatch<infer State> ? State : void
+
) {
+
if (
+
process.env.NODE_ENV !== 'production' &&
+
!!reactSharedInternals &&
+
!!reactSharedInternals.ReactCurrentOwner &&
+
!!reactSharedInternals.ReactCurrentOwner.current
+
) {
+
Promise.resolve(value).then(setState);
+
} else {
+
setState(value);
+
}
+
}
+3 -3
packages/react-urql/src/hooks/useMutation.ts
···
} 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.
*
···
const executeMutation = useCallback(
(variables: Variables, context?: Partial<OperationContext>) => {
-
setState({ ...initialState, fetching: true });
+
deferDispatch(setState, { ...initialState, fetching: true });
return pipe(
client.executeMutation<Data, Variables>(
···
toPromise
).then(result => {
if (isMounted.current) {
-
setState({
+
deferDispatch(setState, {
fetching: false,
stale: !!result.stale,
data: result.data,
+9 -3
packages/react-urql/src/hooks/useQuery.ts
···
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.
*
···
const updateResult = (result: Partial<UseQueryState<Data, Variables>>) => {
hasResult = true;
-
setState(state => {
+
deferDispatch(setState, state => {
const nextResult = computeNextState(state[1], result);
return state[1] !== nextResult
? [state[0], nextResult, state[2]]
···
...opts,
};
-
setState(state => {
+
deferDispatch(setState, state => {
const source = suspense
? pipe(
client.executeQuery(request, context),
+9 -3
packages/react-urql/src/hooks/useSubscription.ts
···
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.
*
···
const updateResult = (
result: Partial<UseSubscriptionState<Data, Variables>>
) => {
-
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) {
···
...opts,
});
-
setState(state => [source, state[1], deps]);
+
deferDispatch(setState, state => [source, state[1], deps]);
},
[client, args.context, request]
);