From e9d9d6a4aa79d14a7c89d7108c0136023a31874e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcholas=20Andr=C3=A9?= Date: Wed, 26 Jul 2023 11:10:46 -0300 Subject: [PATCH] feat: mutate additional cache keys in useFetch --- .../data/strategies/AbstractFetchStrategy.ts | 13 +++++---- .../strategies/PostOrPostsFetchStrategy.ts | 12 +++----- packages/core/src/react/hooks/types.ts | 1 + packages/core/src/react/hooks/useFetch.ts | 29 ++++++++++++++++--- .../src/react/hooks/useFetchPostOrPosts.ts | 17 +++++++++-- .../next/src/data/hooks/usePostOrPosts.ts | 1 + .../next/src/data/server/fetchHookData.ts | 8 +---- .../wp-nextjs/src/components/PageContent.js | 6 +++- .../wp-nextjs/src/pages/blog/[[...path]].js | 12 ++++++-- 9 files changed, 68 insertions(+), 31 deletions(-) diff --git a/packages/core/src/data/strategies/AbstractFetchStrategy.ts b/packages/core/src/data/strategies/AbstractFetchStrategy.ts index f27fcf403..6d3136fc3 100644 --- a/packages/core/src/data/strategies/AbstractFetchStrategy.ts +++ b/packages/core/src/data/strategies/AbstractFetchStrategy.ts @@ -329,20 +329,21 @@ export abstract class AbstractFetchStrategy) { return { url: this.getDefaultEndpoint(), args: { ...params, sourceUrl: this.baseURL } }; } /** - * Normalize data for cache + * Normalize data for cache. * - * @param data - * @param params + * @param data The fetch response data + * @param params The request params */ normalizeForCache( data: FetchResponse, diff --git a/packages/core/src/data/strategies/PostOrPostsFetchStrategy.ts b/packages/core/src/data/strategies/PostOrPostsFetchStrategy.ts index 1b1ca345f..2d476c3f6 100644 --- a/packages/core/src/data/strategies/PostOrPostsFetchStrategy.ts +++ b/packages/core/src/data/strategies/PostOrPostsFetchStrategy.ts @@ -160,7 +160,7 @@ export class PostOrPostsFetchStrategy< try { const results = await this.postStrategy.fetcher( singleURL, - params.single ?? {}, + singleParams, options, ); @@ -182,7 +182,7 @@ export class PostOrPostsFetchStrategy< try { const results = await this.postsStrategy.fetcher( archiveURL, - params.archive ?? {}, + archiveParams, options, ); @@ -211,7 +211,7 @@ export class PostOrPostsFetchStrategy< try { const results = await this.postsStrategy.fetcher( archiveURL, - params.archive ?? {}, + archiveParams, options, ); @@ -230,11 +230,7 @@ export class PostOrPostsFetchStrategy< if (shouldFetchSingle) { try { - const results = await this.postStrategy.fetcher( - singleURL, - params.single ?? {}, - options, - ); + const results = await this.postStrategy.fetcher(singleURL, singleParams, options); return { ...results, diff --git a/packages/core/src/react/hooks/types.ts b/packages/core/src/react/hooks/types.ts index cb5063a8f..c24d2c626 100644 --- a/packages/core/src/react/hooks/types.ts +++ b/packages/core/src/react/hooks/types.ts @@ -11,4 +11,5 @@ export interface HookResponse { export interface FetchHookOptions { fetchStrategyOptions?: Partial; swr?: SWRConfiguration; + shouldFetch?: boolean; } diff --git a/packages/core/src/react/hooks/useFetch.ts b/packages/core/src/react/hooks/useFetch.ts index 54a125ada..36d3d921b 100644 --- a/packages/core/src/react/hooks/useFetch.ts +++ b/packages/core/src/react/hooks/useFetch.ts @@ -1,4 +1,4 @@ -import useSWR from 'swr'; +import useSWR, { useSWRConfig } from 'swr'; import deepmerge from 'deepmerge'; import type { EndpointParams, FetchResponse } from '../../data'; import { AbstractFetchStrategy } from '../../data'; @@ -31,6 +31,7 @@ export function useFetch( path = '', ) { const { sourceUrl, debug } = useSettings(); + const { mutate } = useSWRConfig(); fetchStrategy.setBaseURL(sourceUrl); @@ -40,7 +41,7 @@ export function useFetch( const finalParams = deepmerge.all([defaultParams, urlParams, params]) as Partial; - const { fetchStrategyOptions, ...validSWROptions } = options; + const { fetchStrategyOptions, shouldFetch = true, ...validSWROptions } = options; // for backwards compat ensure options.swr exists // this would make code that's not namespacing the swr options under `{ swr }` still work. @@ -63,8 +64,28 @@ export function useFetch( } const result = useSWR>( - key, - () => fetchStrategy.fetcher(endpointUrl, finalParams, fetchStrategyOptions), + shouldFetch ? key : null, + async () => { + const fetchData = await fetchStrategy.fetcher( + endpointUrl, + finalParams, + fetchStrategyOptions, + ); + + const { data, additionalCacheObjects } = fetchStrategy.normalizeForCache( + fetchData, + finalParams, + ); + + // mutate additiional cache objects + if (additionalCacheObjects) { + additionalCacheObjects.forEach(({ key, data }) => { + mutate(key, data); + }); + } + + return data; + }, options.swr, ); diff --git a/packages/core/src/react/hooks/useFetchPostOrPosts.ts b/packages/core/src/react/hooks/useFetchPostOrPosts.ts index 872cecf92..42032e1b5 100644 --- a/packages/core/src/react/hooks/useFetchPostOrPosts.ts +++ b/packages/core/src/react/hooks/useFetchPostOrPosts.ts @@ -44,9 +44,20 @@ export function useFetchPostOrPosts< path, ); - // TODO: should fetch - const { data: postData } = useFetchPost(params.single, undefined, path); - const { data: postsData } = useFetchPosts(params.archive, undefined, path); + const { data: postData } = useFetchPost( + params.single, + { + shouldFetch: data?.result.isSingle ?? false, + }, + path, + ); + const { data: postsData } = useFetchPosts( + params.archive, + { + shouldFetch: data?.result.isArchive ?? false, + }, + path, + ); if (error || !data) { const fakeData = { diff --git a/packages/next/src/data/hooks/usePostOrPosts.ts b/packages/next/src/data/hooks/usePostOrPosts.ts index 88d16b26a..8a33bed8e 100644 --- a/packages/next/src/data/hooks/usePostOrPosts.ts +++ b/packages/next/src/data/hooks/usePostOrPosts.ts @@ -8,6 +8,7 @@ import { FetchHookOptions, useFetchPostOrPosts } from '@headstartwp/core/react'; import { usePrepareFetch } from './usePrepareFetch'; /** + * The usePostOrPosts hook * * @param params The parameters accepted by the hook * @param options Options for the SWR configuration diff --git a/packages/next/src/data/server/fetchHookData.ts b/packages/next/src/data/server/fetchHookData.ts index f4b7f2558..b122fb3cd 100644 --- a/packages/next/src/data/server/fetchHookData.ts +++ b/packages/next/src/data/server/fetchHookData.ts @@ -152,7 +152,7 @@ export async function fetchHookData ({ ...cacheObject, key: serializeKey(cacheObject.key), - isMainQuerty: fetchStrategy.isMainQuery(stringPath, params), + isMainQuery: fetchStrategy.isMainQuery(stringPath, params), })); } @@ -162,10 +162,4 @@ export async function fetchHookData), - isMainQuery: fetchStrategy.isMainQuery(stringPath, params), - }; */ } diff --git a/projects/wp-nextjs/src/components/PageContent.js b/projects/wp-nextjs/src/components/PageContent.js index 3a35cea6c..b0a7bbe1c 100644 --- a/projects/wp-nextjs/src/components/PageContent.js +++ b/projects/wp-nextjs/src/components/PageContent.js @@ -16,7 +16,11 @@ const Blocks = dynamic(() => import('./Blocks')); export const PageContent = ({ params }) => { // This won't require a refetch as long as the data has already been fetched at the page level. // additionally, if the request has not been SSR'd, it will be fetched on the client only once, regardless of how many call to usePost (with the same params) you make - const { data } = usePost(params); + const { data, loading } = usePost(params); + + if (loading) { + return 'loading'; + } return ( <> diff --git a/projects/wp-nextjs/src/pages/blog/[[...path]].js b/projects/wp-nextjs/src/pages/blog/[[...path]].js index 060edf831..23adefce5 100644 --- a/projects/wp-nextjs/src/pages/blog/[[...path]].js +++ b/projects/wp-nextjs/src/pages/blog/[[...path]].js @@ -22,7 +22,11 @@ import { resolveBatch } from '../../utils/promises'; import { PageContent } from '../../components/PageContent'; const Archive = () => { - const { data } = usePosts(blogParams.archive); + const { data, loading } = usePosts(blogParams.archive); + + if (loading) { + return 'loading usePosts'; + } return ( <> @@ -39,7 +43,11 @@ const Archive = () => { }; const BlogPage = () => { - const { isArchive } = usePostOrPosts(blogParams); + const { isArchive, loading } = usePostOrPosts(blogParams); + + if (loading) { + return 'Loading usePostOrPosts'; + } if (isArchive) { return ;