Created
December 28, 2022 13:26
-
-
Save fdecampredon/e8e977ea935d8b74ab82afbd3a5b6cf3 to your computer and use it in GitHub Desktop.
Revisions
-
fdecampredon renamed this gist
Dec 28, 2022 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
fdecampredon created this gist
Dec 28, 2022 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,74 @@ import { graphql } from 'graphql'; import schema from './your_schema_path'; import type { VariablesOf, GraphQLTaggedNode } from 'react-relay'; import type { ConcreteRequest, PayloadData, OperationType, } from 'relay-runtime'; export type ServerQuery<TQuery extends OperationType> = { id: string; variables: VariablesOf<TQuery>; payload: PayloadData; }; const preloadServerQuery = async <TQuery extends OperationType>( gqlQuery: GraphQLTaggedNode, variables: VariablesOf<TQuery>, ): Promise<ServerQuery<TQuery>> => { if (typeof gqlQuery === 'function') { gqlQuery = gqlQuery(); } if (gqlQuery.kind !== 'Request') { throw new Error( 'preloadServerQuery: Expected a graphql`...` tagged query.', ); } const request = gqlQuery as ConcreteRequest; const { params } = request; const queryVariables = { ...variables }; const { providedVariables } = params as any; if (providedVariables) { Object.keys(providedVariables).forEach(key => { //@ts-expect-error no types queryVariables[key] = params.providedVariables[key].get(); }); } // fetch instead of graphql if necessary const response = await graphql({ schema, // handle persisted queries is necessary source: params.text as string, variableValues: queryVariables, }); return { id: params.id ?? params.cacheID!, variables, // see https://github.com/apollographql/apollo-server/issues/3149#issuecomment-1117566982 payload: normalizeObject(response.data), }; }; export default preloadServerQuery; const normalizeObject = (obj: any): any => { if (typeof obj !== 'object' || obj == null) { return obj; } if (Array.isArray(obj)) { return obj.map(normalizeObject); } if (!(obj instanceof Object)) { const res = {} as any; const keys = Object.keys(obj); for (const key of keys) { res[key] = normalizeObject(obj[key]); } obj = res; } return obj; }; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,41 @@ import { useMemo } from 'react'; import { useRelayEnvironment } from 'react-relay'; // @ts-expect-error no types import useLazyLoadQueryNode from 'react-relay/lib/relay-hooks/useLazyLoadQueryNode'; // @ts-expect-error no types import useMemoOperationDescriptor from 'react-relay/lib/relay-hooks/useMemoOperationDescriptor'; import { __internal } from 'relay-runtime'; import type { ServerQuery } from './preloadServerQuery'; import type { OperationType, GraphQLTaggedNode } from 'relay-runtime'; const { fetchQuery } = __internal; function useServerQuery<TQuery extends OperationType>( gqlQuery: GraphQLTaggedNode, serverQuery: ServerQuery<TQuery>, ): TQuery['response'] { const environment = useRelayEnvironment(); const operation = useMemoOperationDescriptor(gqlQuery, serverQuery.variables); if (operation.request.node.params.id !== serverQuery.id) { throw Error( `useServerQuery(): Mismatched version for query '${operation.request.node.params.name}'`, ); } // ugly hack to avoid commiting the payload multiple times useMemo(() => { environment.commitPayload(operation, serverQuery.payload); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return useLazyLoadQueryNode({ componentDisplayName: 'useServerQuery()', fetchKey: null, fetchPolicy: 'store-only', fetchObservable: fetchQuery(environment, operation), query: operation, renderPolicy: null, }); } export default useServerQuery;