feat: cache search results (#869)

This commit is contained in:
Daniel Lautzenheiser 2023-09-07 08:54:59 -04:00 committed by GitHub
parent 6022ead87a
commit 1c8ff049c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 3 deletions

View File

@ -2,6 +2,7 @@ import isEqual from 'lodash/isEqual';
import { currentBackend } from '../backend'; import { currentBackend } from '../backend';
import { import {
CLEAR_REQUESTS,
QUERY_FAILURE, QUERY_FAILURE,
QUERY_REQUEST, QUERY_REQUEST,
QUERY_SUCCESS, QUERY_SUCCESS,
@ -13,7 +14,7 @@ import {
import type { AnyAction } from 'redux'; import type { AnyAction } from 'redux';
import type { ThunkDispatch } from 'redux-thunk'; import type { ThunkDispatch } from 'redux-thunk';
import type { Entry, SearchQueryResponse } from '../interface'; import type { Entry, SearchQueryRequest, SearchQueryResponse } from '../interface';
import type { RootState } from '../store'; import type { RootState } from '../store';
/* /*
@ -44,11 +45,12 @@ export function searchFailure(error: Error) {
} as const; } as const;
} }
export function querying(searchTerm: string) { export function querying(searchTerm: string, request?: SearchQueryRequest) {
return { return {
type: QUERY_REQUEST, type: QUERY_REQUEST,
payload: { payload: {
searchTerm, searchTerm,
request,
}, },
} as const; } as const;
} }
@ -78,6 +80,10 @@ export function clearSearch() {
return { type: SEARCH_CLEAR } as const; return { type: SEARCH_CLEAR } as const;
} }
export function clearRequests() {
return { type: CLEAR_REQUESTS } as const;
}
/* /*
* Exported Thunk Action Creators * Exported Thunk Action Creators
*/ */
@ -180,4 +186,5 @@ export type SearchAction = ReturnType<
| typeof querySuccess | typeof querySuccess
| typeof queryFailure | typeof queryFailure
| typeof clearSearch | typeof clearSearch
| typeof clearRequests
>; >;

View File

@ -110,6 +110,7 @@ export const QUERY_SUCCESS = 'QUERY_SUCCESS';
export const QUERY_FAILURE = 'QUERY_FAILURE'; export const QUERY_FAILURE = 'QUERY_FAILURE';
export const SEARCH_CLEAR = 'SEARCH_CLEAR'; export const SEARCH_CLEAR = 'SEARCH_CLEAR';
export const CLEAR_REQUESTS = 'CLEAR_REQUESTS';
// Status // Status
export const STATUS_REQUEST = 'STATUS_REQUEST'; export const STATUS_REQUEST = 'STATUS_REQUEST';

View File

@ -1037,6 +1037,12 @@ export interface SearchResponse {
pagination: number; pagination: number;
} }
export type SearchQueryRequest = {
id: string;
expires: Date;
queryResponse: Promise<SearchQueryResponse>;
};
export interface SearchQueryResponse { export interface SearchQueryResponse {
hits: Entry[]; hits: Entry[];
query: string; query: string;

View File

@ -1,4 +1,5 @@
import { import {
CLEAR_REQUESTS,
QUERY_FAILURE, QUERY_FAILURE,
QUERY_REQUEST, QUERY_REQUEST,
QUERY_SUCCESS, QUERY_SUCCESS,
@ -9,6 +10,7 @@ import {
} from '../constants'; } from '../constants';
import type { SearchAction } from '../actions/search'; import type { SearchAction } from '../actions/search';
import type { SearchQueryRequest } from '../interface';
export interface SearchState { export interface SearchState {
isFetching: boolean; isFetching: boolean;
@ -17,6 +19,7 @@ export interface SearchState {
page: number; page: number;
entryIds: { collection: string; slug: string }[]; entryIds: { collection: string; slug: string }[];
error: Error | undefined; error: Error | undefined;
requests: SearchQueryRequest[];
} }
const defaultState: SearchState = { const defaultState: SearchState = {
@ -26,6 +29,7 @@ const defaultState: SearchState = {
page: 0, page: 0,
entryIds: [], entryIds: [],
error: undefined, error: undefined,
requests: [],
}; };
const search = (state: SearchState = defaultState, action: SearchAction): SearchState => { const search = (state: SearchState = defaultState, action: SearchAction): SearchState => {
@ -66,14 +70,26 @@ const search = (state: SearchState = defaultState, action: SearchAction): Search
} }
case QUERY_REQUEST: { case QUERY_REQUEST: {
const { searchTerm } = action.payload; const { searchTerm, request } = action.payload;
const requests = [...state.requests];
if (request) {
requests.push(request);
}
return { return {
...state, ...state,
isFetching: true, isFetching: true,
term: searchTerm, term: searchTerm,
requests,
}; };
} }
case CLEAR_REQUESTS: {
state.requests = state.requests.filter(req => req.expires >= new Date());
break;
}
case QUERY_SUCCESS: { case QUERY_SUCCESS: {
return { return {
...state, ...state,