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

feat: useWizardApiFetch add manual cache handling logic #3480

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Changes from all 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
66 changes: 55 additions & 11 deletions src/wizards/hooks/use-wizard-api-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ import { useState, useCallback, useEffect, useRef } from '@wordpress/element';
import { WIZARD_STORE_NAMESPACE } from '../../components/src/wizard/store';
import { WizardApiError } from '../errors';

/**
* Remove query arguments from a path. Similar to `removeQueryArgs` in `@wordpress/url`, but this function
* removes all query arguments from a string and returns it.
*
* @param str String to remove query arguments from.
* @return The string without query arguments.
*/
function removeQueryArgs( str: string ) {
return str.split( '?' ).at( 0 ) ?? str;
}

/**
* Holds in-progress promises for each fetch request.
*/
Expand Down Expand Up @@ -107,19 +118,37 @@ export function useWizardApiFetch( slug: string ) {
/**
* Updates the wizard data at the specified path.
*
* @param path The path to update in the wizard data.
* @param cacheKeyPath The cacheKeyPath to update in the wizard data.
* @return Function to update the wizard data.
*/
function updateWizardData( path: string | null ) {
return ( prop: string | string[], value: any, p = path ) =>
function updateWizardData( cacheKeyPath: string | null ) {
/**
* Updates the wizard data prop at the specified path.
*
* @param prop The property to update in the wizard path data. i.e. 'GET'
* @param value The value to set for the property.
* @param cacheKeyPathOverride The path to update in the wizard data.
*/
return (
prop: string | string[],
value: any,
cacheKeyPathOverride = cacheKeyPath
) => {
// Remove query parameters from the cacheKeyPath

const normalizedPath = cacheKeyPathOverride
? removeQueryArgs( cacheKeyPathOverride )
: cacheKeyPathOverride;

updateWizardSettings( {
slug,
path: [
p,
normalizedPath,
...( Array.isArray( prop ) ? prop : [ prop ] ),
].filter( str => typeof str === 'string' ),
value,
} );
};
}

/**
Expand All @@ -138,6 +167,7 @@ export function useWizardApiFetch( slug: string ) {
const { on } = onCallbacks< T >( callbacks ?? {} );
const updateSettings = updateWizardData( opts.path );
const { path, method = 'GET' } = opts;
const cacheKeyPath = removeQueryArgs( path ?? '' );
const {
isCached = method === 'GET',
updateCacheKey = null,
Expand All @@ -147,7 +177,7 @@ export function useWizardApiFetch( slug: string ) {

const {
error: cachedError,
[ path ]: { [ method ]: cachedMethod = null } = {},
[ cacheKeyPath ]: { [ method ]: cachedMethod = null } = {},
}: WizardData = wizardData;

function thenCallback( response: T ) {
Expand Down Expand Up @@ -197,19 +227,19 @@ export function useWizardApiFetch( slug: string ) {

function finallyCallback() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { [ path ]: _removed, ...newData } = promiseCache;
const { [ cacheKeyPath ]: _removed, ...newData } = promiseCache;
promiseCache = newData;
requests.current = requests.current.filter(
request => request !== path
request => request !== cacheKeyPath
);
setIsFetching( requests.current.length > 0 );
on( 'onFinally' );
}

// If the promise is already in progress, return it before making a new request.
if ( promiseCache[ path ] ) {
if ( promiseCache[ cacheKeyPath ] ) {
setIsFetching( true );
return promiseCache[ path ]
return promiseCache[ cacheKeyPath ]
.then( thenCallback )
.catch( catchCallback )
.finally( finallyCallback );
Expand All @@ -224,9 +254,9 @@ export function useWizardApiFetch( slug: string ) {

setIsFetching( true );
on( 'onStart' );
requests.current.push( path );
requests.current.push( cacheKeyPath );

promiseCache[ path ] = wizardApiFetch( {
promiseCache[ cacheKeyPath ] = wizardApiFetch( {
isQuietFetch: true,
isLocalError: true,
...options,
Expand All @@ -245,6 +275,20 @@ export function useWizardApiFetch( slug: string ) {
isFetching,
errorMessage: error ? error.message : null,
error,
cache( cacheKey: string ) {
return {
get( method: ApiMethods = 'GET' ) {
return wizardData[ cacheKey ][ method ];
},
set( value: any, method: ApiMethods = 'GET' ) {
updateWizardSettings( {
slug,
path: [ cacheKey, method ],
value,
} );
},
};
},
setError(
value: string | WizardErrorType | null | { message: string }
) {
Expand Down