diff --git a/issue-tracker-next-v13/app/layout.tsx b/issue-tracker-next-v13/app/layout.tsx index 604bfc1b..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 { getCurrentEnvironment } 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 = getCurrentEnvironment(); + 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 a0825d5b..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, @@ -11,7 +12,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 +56,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 +79,48 @@ 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; } + +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 +>(); + +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,