From 7cd8737a89b47ae5ab31b88ee5d0dcc9ff8da336 Mon Sep 17 00:00:00 2001 From: Baris Tikir Date: Sun, 7 May 2023 12:06:06 +0200 Subject: [PATCH 1/2] Fix QueryResponseCache usage for Preloaded Queries --- issue-tracker-next-v13/app/layout.tsx | 4 +- .../src/relay/environment.ts | 44 +++++++++++-------- .../relay/useSerializablePreloadedQuery.ts | 15 ++++--- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/issue-tracker-next-v13/app/layout.tsx b/issue-tracker-next-v13/app/layout.tsx index 604bfc1b..3cad2bfa 100644 --- a/issue-tracker-next-v13/app/layout.tsx +++ b/issue-tracker-next-v13/app/layout.tsx @@ -1,7 +1,7 @@ "use client"; import { RelayEnvironmentProvider } from "react-relay"; -import { getCurrentEnvironment } from "src/relay/environment"; +import { createEnvironment } from "src/relay/environment"; import "styles/globals.css"; import styles from "styles/layout.module.css"; @@ -11,7 +11,7 @@ export default function RootLayout({ }: { children: React.ReactNode; }) { - const environment = getCurrentEnvironment(); + const environment = createEnvironment(); return ( diff --git a/issue-tracker-next-v13/src/relay/environment.ts b/issue-tracker-next-v13/src/relay/environment.ts index a0825d5b..8300cf0d 100644 --- a/issue-tracker-next-v13/src/relay/environment.ts +++ b/issue-tracker-next-v13/src/relay/environment.ts @@ -11,7 +11,6 @@ import { } from "relay-runtime"; const HTTP_ENDPOINT = "https://api.github.com/graphql"; -const IS_SERVER = typeof window === typeof undefined; const CACHE_TTL = 5 * 1000; // 5 seconds, to resolve preloaded results export async function networkFetch( @@ -56,14 +55,7 @@ export async function networkFetch( return json; } -export const responseCache: QueryResponseCache | null = IS_SERVER - ? null - : new QueryResponseCache({ - size: 100, - ttl: CACHE_TTL, - }); - -function createNetwork() { +function createNetwork(responseCache: QueryResponseCache) { async function fetchResponse( params: RequestParameters, variables: Variables, @@ -86,20 +78,34 @@ function createNetwork() { return network; } -function createEnvironment() { - return new Environment({ - network: createNetwork(), - store: new Store(RecordSource.create()), - isServer: IS_SERVER, +function createQueryCache() { + return new QueryResponseCache({ + size: 100, + ttl: CACHE_TTL, }); } -export const environment = createEnvironment(); +export function createEnvironment() { + const cache = createQueryCache(); + const network = createNetwork(cache); + const store = new Store(RecordSource.create()); -export function getCurrentEnvironment() { - if (IS_SERVER) { - return createEnvironment(); - } + const environment = new Environment({ + network, + store, + isServer: typeof window === "undefined", + }); + + responseCacheByEnvironment.set(environment, cache); return environment; } + +const responseCacheByEnvironment = new WeakMap< + Environment, + QueryResponseCache +>(); + +export function getCacheByEnvironment(environment: Environment) { + return responseCacheByEnvironment.get(environment); +} diff --git a/issue-tracker-next-v13/src/relay/useSerializablePreloadedQuery.ts b/issue-tracker-next-v13/src/relay/useSerializablePreloadedQuery.ts index 75a8beff..a0e2ac76 100644 --- a/issue-tracker-next-v13/src/relay/useSerializablePreloadedQuery.ts +++ b/issue-tracker-next-v13/src/relay/useSerializablePreloadedQuery.ts @@ -3,8 +3,8 @@ import { useMemo } from "react"; import { PreloadedQuery, PreloadFetchPolicy } from "react-relay"; -import { ConcreteRequest, IEnvironment, OperationType } from "relay-runtime"; -import { responseCache } from "./environment"; +import { ConcreteRequest, Environment, OperationType } from "relay-runtime"; +import { getCacheByEnvironment } from "./environment"; import { SerializablePreloadedQuery } from "./loadSerializableQuery"; // This hook convert serializable preloaded query @@ -17,12 +17,12 @@ export default function useSerializablePreloadedQuery< TRequest extends ConcreteRequest, TQuery extends OperationType >( - environment: IEnvironment, + environment: Environment, preloadQuery: SerializablePreloadedQuery, fetchPolicy: PreloadFetchPolicy = "store-or-network" ): PreloadedQuery { useMemo(() => { - writePreloadedQueryToCache(preloadQuery); + writePreloadedQueryToCache(preloadQuery, environment); }, [preloadQuery]); return { @@ -42,9 +42,14 @@ export default function useSerializablePreloadedQuery< function writePreloadedQueryToCache< TRequest extends ConcreteRequest, TQuery extends OperationType ->(preloadedQueryObject: SerializablePreloadedQuery) { +>( + preloadedQueryObject: SerializablePreloadedQuery, + environment: Environment +) { const cacheKey = preloadedQueryObject.params.id ?? preloadedQueryObject.params.cacheID; + const responseCache = getCacheByEnvironment(environment); + responseCache?.set( cacheKey, preloadedQueryObject.variables, From f7ee9f489e9fb9193cfd746b24b1435d6630456e Mon Sep 17 00:00:00 2001 From: Baris Tikir Date: Sun, 7 May 2023 19:29:57 +0200 Subject: [PATCH 2/2] Fix Infinite Rerender Loop for Environment Creation --- issue-tracker-next-v13/app/layout.tsx | 4 ++-- issue-tracker-next-v13/src/relay/environment.ts | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/issue-tracker-next-v13/app/layout.tsx b/issue-tracker-next-v13/app/layout.tsx index 3cad2bfa..444f9676 100644 --- a/issue-tracker-next-v13/app/layout.tsx +++ b/issue-tracker-next-v13/app/layout.tsx @@ -1,7 +1,7 @@ "use client"; import { RelayEnvironmentProvider } from "react-relay"; -import { createEnvironment } from "src/relay/environment"; +import { useEnvironment } from "src/relay/environment"; import "styles/globals.css"; import styles from "styles/layout.module.css"; @@ -11,7 +11,7 @@ export default function RootLayout({ }: { children: React.ReactNode; }) { - const environment = createEnvironment(); + const environment = useEnvironment(); return ( diff --git a/issue-tracker-next-v13/src/relay/environment.ts b/issue-tracker-next-v13/src/relay/environment.ts index 8300cf0d..7e34c897 100644 --- a/issue-tracker-next-v13/src/relay/environment.ts +++ b/issue-tracker-next-v13/src/relay/environment.ts @@ -1,3 +1,4 @@ +import { useMemo } from "react"; import { Environment, Network, @@ -101,6 +102,20 @@ export function createEnvironment() { return environment; } +let relayEnvironment: Environment | null = null; +function initEnvironment() { + const environment = relayEnvironment ?? createEnvironment(); + // For SSR always return new environment; + if (typeof window === "undefined") return environment; + if (!relayEnvironment) relayEnvironment = environment; + return relayEnvironment; +} + +export function useEnvironment() { + const env = useMemo(() => initEnvironment(), [relayEnvironment]); + return env; +} + const responseCacheByEnvironment = new WeakMap< Environment, QueryResponseCache