Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use import * as React everywhere. #11000

Merged
merged 7 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/large-beers-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@apollo/client': patch
---

Use `import * as React` everywhere. This prevents an error when importing `@apollo/client` in a React Server component. (see [#10974](https://github.com/apollographql/apollo-client/issues/10974))
2 changes: 1 addition & 1 deletion .size-limit.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const checks = [
{
path: "dist/apollo-client.min.cjs",
limit: "37700"
limit: "37796"
},
{
path: "dist/main.cjs",
Expand Down
2 changes: 1 addition & 1 deletion src/react/hooks/internal/__use.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { wrapPromiseWithState } from '../../../utilities';
import React from 'react';
import * as React from 'react';

type Use = <T>(promise: Promise<T>) => T;
// Prevent webpack from complaining about our feature detection of the
Expand Down
4 changes: 2 additions & 2 deletions src/react/hooks/internal/useDeepMemo.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { DependencyList } from 'react';
import { useRef } from 'react';
import * as React from 'react';
import { equal } from '@wry/equality';

export function useDeepMemo<TValue>(
memoFn: () => TValue,
deps: DependencyList
) {
const ref = useRef<{ deps: DependencyList; value: TValue }>();
const ref = React.useRef<{ deps: DependencyList; value: TValue }>();

if (!ref.current || !equal(ref.current.deps, deps)) {
ref.current = { value: memoFn(), deps };
Expand Down
6 changes: 3 additions & 3 deletions src/react/hooks/internal/useIsomorphicLayoutEffect.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useLayoutEffect, useEffect } from 'react';
import * as React from 'react';
import { canUseDOM } from '../../../utilities';

// use canUseDOM here instead of canUseLayoutEffect because we want to be able
Expand All @@ -7,5 +7,5 @@ import { canUseDOM } from '../../../utilities';
// warnings for useSyncExternalStore implementation, canUseLayoutEffect is left
// alone.
export const useIsomorphicLayoutEffect = canUseDOM
? useLayoutEffect
: useEffect;
? React.useLayoutEffect
: React.useEffect;
4 changes: 2 additions & 2 deletions src/react/hooks/internal/useStrictModeSafeCleanupEffect.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useEffect } from 'react';
import * as React from 'react';

export function useStrictModeSafeCleanupEffect(cleanup: () => void) {
let timeout: NodeJS.Timeout;

useEffect(() => {
React.useEffect(() => {
clearTimeout(timeout);

return () => {
Expand Down
4 changes: 2 additions & 2 deletions src/react/hooks/useApolloClient.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { invariant } from '../../utilities/globals';
import { useContext } from 'react';
import * as React from 'react';
import type { ApolloClient } from '../../core';
import { getApolloContext } from '../context';

export function useApolloClient(
override?: ApolloClient<object>,
): ApolloClient<object> {
const context = useContext(getApolloContext());
const context = React.useContext(getApolloContext());
const client = override || context.client;
invariant(
!!client,
Expand Down
18 changes: 9 additions & 9 deletions src/react/hooks/useBackgroundQuery.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState, useMemo, useCallback } from 'react';
import * as React from 'react';
import type {
DocumentNode,
OperationVariables,
Expand Down Expand Up @@ -147,7 +147,7 @@ export function useBackgroundQuery<

const { fetchPolicy: currentFetchPolicy } = queryRef.watchQueryOptions;

const [promiseCache, setPromiseCache] = useState(
const [promiseCache, setPromiseCache] = React.useState(
() => new Map([[queryRef.key, queryRef.promise]])
);

Expand All @@ -158,7 +158,7 @@ export function useBackgroundQuery<

useTrackedQueryRefs(queryRef);

const fetchMore: FetchMoreFunction<TData, TVariables> = useCallback(
const fetchMore: FetchMoreFunction<TData, TVariables> = React.useCallback(
(options) => {
const promise = queryRef.fetchMore(options);

Expand All @@ -171,7 +171,7 @@ export function useBackgroundQuery<
[queryRef]
);

const refetch: RefetchFunction<TData, TVariables> = useCallback(
const refetch: RefetchFunction<TData, TVariables> = React.useCallback(
(variables) => {
const promise = queryRef.refetch(variables);

Expand All @@ -186,7 +186,7 @@ export function useBackgroundQuery<

queryRef.promiseCache = promiseCache;

return useMemo(() => {
return React.useMemo(() => {
return [
queryRef,
{
Expand All @@ -198,7 +198,7 @@ export function useBackgroundQuery<
}

export function useReadQuery<TData>(queryRef: QueryReference<TData>) {
const [, forceUpdate] = useState(0);
const [, forceUpdate] = React.useState(0);

invariant(
queryRef.promiseCache,
Expand All @@ -207,7 +207,7 @@ export function useReadQuery<TData>(queryRef: QueryReference<TData>) {
'Please ensure you are passing the `queryRef` returned from `useBackgroundQuery`.'
);

const skipResult = useMemo(() => {
const skipResult = React.useMemo(() => {
const error = toApolloError(queryRef.result);

return {
Expand All @@ -225,7 +225,7 @@ export function useReadQuery<TData>(queryRef: QueryReference<TData>) {
queryRef.promiseCache.set(queryRef.key, promise);
}

useEffect(() => {
React.useEffect(() => {
return queryRef.listen((promise) => {
queryRef.promiseCache!.set(queryRef.key, promise);
forceUpdate((prevState) => prevState + 1);
Expand All @@ -237,7 +237,7 @@ export function useReadQuery<TData>(queryRef: QueryReference<TData>) {
? skipResult
: __use(promise);

return useMemo(() => {
return React.useMemo(() => {
return {
data: result.data,
networkStatus: result.networkStatus,
Expand Down
12 changes: 6 additions & 6 deletions src/react/hooks/useLazyQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { DocumentNode } from 'graphql';
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
import { useCallback, useMemo, useRef } from 'react';
import * as React from 'react';

import type { OperationVariables } from '../../core';
import { mergeOptions } from '../../utilities';
Expand Down Expand Up @@ -29,9 +29,9 @@ export function useLazyQuery<TData = any, TVariables extends OperationVariables
query: DocumentNode | TypedDocumentNode<TData, TVariables>,
options?: LazyQueryHookOptions<NoInfer<TData>, NoInfer<TVariables>>
): LazyQueryResultTuple<TData, TVariables> {
const execOptionsRef = useRef<Partial<LazyQueryHookExecOptions<TData, TVariables>>>();
const optionsRef = useRef<LazyQueryHookOptions<TData, TVariables>>();
const queryRef = useRef<DocumentNode | TypedDocumentNode<TData, TVariables>>();
const execOptionsRef = React.useRef<Partial<LazyQueryHookExecOptions<TData, TVariables>>>();
const optionsRef = React.useRef<LazyQueryHookOptions<TData, TVariables>>();
const queryRef = React.useRef<DocumentNode | TypedDocumentNode<TData, TVariables>>();
const merged = mergeOptions(options, execOptionsRef.current || {});
const document = merged?.query ?? query;

Expand Down Expand Up @@ -60,7 +60,7 @@ export function useLazyQuery<TData = any, TVariables extends OperationVariables
});

// We use useMemo here to make sure the eager methods have a stable identity.
const eagerMethods = useMemo(() => {
const eagerMethods = React.useMemo(() => {
const eagerMethods: Record<string, any> = {};
for (const key of EAGER_METHODS) {
const method = result[key];
Expand All @@ -79,7 +79,7 @@ export function useLazyQuery<TData = any, TVariables extends OperationVariables

Object.assign(result, eagerMethods);

const execute = useCallback<
const execute = React.useCallback<
LazyQueryResultTuple<TData, TVariables>[0]
>(executeOptions => {
execOptionsRef.current = executeOptions ? {
Expand Down
12 changes: 6 additions & 6 deletions src/react/hooks/useMutation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import * as React from 'react';
import type { DocumentNode } from 'graphql';
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
import type {
Expand Down Expand Up @@ -32,13 +32,13 @@ export function useMutation<
): MutationTuple<TData, TVariables, TContext, TCache> {
const client = useApolloClient(options?.client);
verifyDocumentType(mutation, DocumentType.Mutation);
const [result, setResult] = useState<Omit<MutationResult, 'reset'>>({
const [result, setResult] = React.useState<Omit<MutationResult, 'reset'>>({
called: false,
loading: false,
client,
});

const ref = useRef({
const ref = React.useRef({
result,
mutationId: 0,
isMounted: true,
Expand All @@ -53,7 +53,7 @@ export function useMutation<
Object.assign(ref.current, { client, options, mutation });
}

const execute = useCallback((
const execute = React.useCallback((
executeOptions: MutationFunctionOptions<
TData,
TVariables,
Expand Down Expand Up @@ -140,13 +140,13 @@ export function useMutation<
});
}, []);

const reset = useCallback(() => {
const reset = React.useCallback(() => {
if (ref.current.isMounted) {
setResult({ called: false, loading: false, client });
}
}, []);

useEffect(() => {
React.useEffect(() => {
ref.current.isMounted = true;

return () => {
Expand Down
18 changes: 6 additions & 12 deletions src/react/hooks/useQuery.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { invariant } from '../../utilities/globals';

import {
useCallback,
useContext,
useMemo,
useRef,
useState,
} from 'react';
import * as React from 'react';
import { useSyncExternalStore } from './useSyncExternalStore';
import { equal } from '@wry/equality';

Expand Down Expand Up @@ -59,7 +53,7 @@ export function useInternalState<TData, TVariables extends OperationVariables>(
client: ApolloClient<any>,
query: DocumentNode | TypedDocumentNode<TData, TVariables>,
): InternalState<TData, TVariables> {
const stateRef = useRef<InternalState<TData, TVariables>>();
const stateRef = React.useRef<InternalState<TData, TVariables>>();
if (
!stateRef.current ||
client !== stateRef.current.client ||
Expand All @@ -75,7 +69,7 @@ export function useInternalState<TData, TVariables extends OperationVariables>(
// setTick function. Updating this state by calling state.forceUpdate is the
// only way we trigger React component updates (no other useState calls within
// the InternalState class).
const [_tick, setTick] = useState(0);
const [_tick, setTick] = React.useState(0);
state.forceUpdate = () => {
setTick(tick => tick + 1);
};
Expand Down Expand Up @@ -159,14 +153,14 @@ class InternalState<TData, TVariables extends OperationVariables> {
// initialization, this.renderPromises is usually undefined (unless SSR is
// happening), but that's fine as long as it has been initialized that way,
// rather than left uninitialized.
this.renderPromises = useContext(getApolloContext()).renderPromises;
this.renderPromises = React.useContext(getApolloContext()).renderPromises;

this.useOptions(options);

const obsQuery = this.useObservableQuery();

const result = useSyncExternalStore(
useCallback(() => {
React.useCallback(() => {
if (this.renderPromises) {
return () => {};
}
Expand Down Expand Up @@ -469,7 +463,7 @@ class InternalState<TData, TVariables extends OperationVariables> {
|| this.observable // Reuse this.observable if possible (and not SSR)
|| this.client.watchQuery(this.getObsQueryOptions());

this.obsQueryFields = useMemo(() => ({
this.obsQueryFields = React.useMemo(() => ({
refetch: obsQuery.refetch.bind(obsQuery),
reobserve: obsQuery.reobserve.bind(obsQuery),
fetchMore: obsQuery.fetchMore.bind(obsQuery),
Expand Down
6 changes: 3 additions & 3 deletions src/react/hooks/useReactiveVar.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { useEffect, useState } from 'react';
import * as React from 'react';
import type { ReactiveVar } from '../../core';

export function useReactiveVar<T>(rv: ReactiveVar<T>): T {
const value = rv();

// We don't actually care what useState thinks the value of the variable
// is, so we take only the update function from the returned array.
const setValue = useState(value)[1];
const setValue = React.useState(value)[1];

// We subscribe to variable updates on initial mount and when the value has
// changed. This avoids a subtle bug in React.StrictMode where multiple
// listeners are added, leading to inconsistent updates.
useEffect(() => {
React.useEffect(() => {
const probablySameValue = rv();
if (value !== probablySameValue) {
// If the value of rv has already changed, we don't need to listen for the
Expand Down
18 changes: 9 additions & 9 deletions src/react/hooks/useSubscription.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { invariant } from '../../utilities/globals';
import { useState, useRef, useEffect } from 'react';
import * as React from 'react';
import type { DocumentNode } from 'graphql';
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
import { equal } from '@wry/equality';
Expand All @@ -17,10 +17,10 @@ export function useSubscription<TData = any, TVariables extends OperationVariabl
subscription: DocumentNode | TypedDocumentNode<TData, TVariables>,
options?: SubscriptionHookOptions<NoInfer<TData>, NoInfer<TVariables>>,
) {
const hasIssuedDeprecationWarningRef = useRef(false);
const hasIssuedDeprecationWarningRef = React.useRef(false);
const client = useApolloClient(options?.client);
verifyDocumentType(subscription, DocumentType.Subscription);
const [result, setResult] = useState<SubscriptionResult<TData, TVariables>>({
const [result, setResult] = React.useState<SubscriptionResult<TData, TVariables>>({
loading: !options?.skip,
error: void 0,
data: void 0,
Expand All @@ -47,7 +47,7 @@ export function useSubscription<TData = any, TVariables extends OperationVariabl
}
}

const [observable, setObservable] = useState(() => {
const [observable, setObservable] = React.useState(() => {
if (options?.skip) {
return null;
}
Expand All @@ -60,15 +60,15 @@ export function useSubscription<TData = any, TVariables extends OperationVariabl
});
});

const canResetObservableRef = useRef(false);
useEffect(() => {
const canResetObservableRef = React.useRef(false);
React.useEffect(() => {
return () => {
canResetObservableRef.current = true;
};
}, []);

const ref = useRef({ client, subscription, options });
useEffect(() => {
const ref = React.useRef({ client, subscription, options });
React.useEffect(() => {
let shouldResubscribe = options?.shouldResubscribe;
if (typeof shouldResubscribe === 'function') {
shouldResubscribe = !!shouldResubscribe(options!);
Expand Down Expand Up @@ -112,7 +112,7 @@ export function useSubscription<TData = any, TVariables extends OperationVariabl
Object.assign(ref.current, { client, subscription, options });
}, [client, subscription, options, canResetObservableRef.current]);

useEffect(() => {
React.useEffect(() => {
if (!observable) {
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/react/hooks/useSuspenseCache.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useContext } from 'react';
import * as React from 'react';
import { getApolloContext } from '../context';
import { invariant } from '../../utilities/globals';
import type { SuspenseCache } from '../cache';

export function useSuspenseCache(override?: SuspenseCache) {
const context = useContext(getApolloContext());
const context = React.useContext(getApolloContext());
const suspenseCache = override || context.suspenseCache;

invariant(
Expand Down
Loading