From 98fc0c36dc0dc4d390b105ebd012e49da959fd03 Mon Sep 17 00:00:00 2001 From: Damon Date: Fri, 10 Jun 2022 13:20:02 +0200 Subject: [PATCH] Add custom merge function option --- packages/lib/search/use-acter-search.ts | 1 + .../pagainated-results.reducer.test.ts | 40 +++++++++++++++++-- .../paginated-results-reducer.ts | 15 ++++--- .../lib/urql/use-paginated-query/types.ts | 23 ++++++++--- .../use-paginated-query.ts | 5 ++- 5 files changed, 68 insertions(+), 16 deletions(-) diff --git a/packages/lib/search/use-acter-search.ts b/packages/lib/search/use-acter-search.ts index ff946e9d0..5547af28f 100644 --- a/packages/lib/search/use-acter-search.ts +++ b/packages/lib/search/use-acter-search.ts @@ -22,6 +22,7 @@ export interface UseActerSearchQueryResults } type UseActerSearchOptions = UsePaginationQueryOptions< + Acter, ActerSearchData, SearchVariables > diff --git a/packages/lib/urql/use-paginated-query/pagainated-results.reducer.test.ts b/packages/lib/urql/use-paginated-query/pagainated-results.reducer.test.ts index 843989b85..ca30cc08c 100644 --- a/packages/lib/urql/use-paginated-query/pagainated-results.reducer.test.ts +++ b/packages/lib/urql/use-paginated-query/pagainated-results.reducer.test.ts @@ -5,7 +5,7 @@ import { GetPaginatedResultsReducer, PaginatedResultsActionKind, PaginatedResultsState, - ResultsType, + StateResultsType, } from './types' describe('paginatedResultsReducer', () => { @@ -134,7 +134,7 @@ describe('paginatedResultsReducer', () => { results: OrderedMap({ 1: { id: 1 }, 2: { id: 2 }, - }) as ResultsType, + }) as StateResultsType, }, { type: PaginatedResultsActionKind.NEW_RESULTS, @@ -156,7 +156,7 @@ describe('paginatedResultsReducer', () => { results: OrderedMap({ 1: { id: 1 }, 2: { id: 2 }, - }) as ResultsType, + }) as StateResultsType, }, { type: PaginatedResultsActionKind.NEW_RESULTS, @@ -172,6 +172,40 @@ describe('paginatedResultsReducer', () => { }) }) + describe('resultsMergeFn', () => { + it('should allow for different merge strategies', () => { + const result = getPaginatedResultsReducer< + { id: number; foo: string }, + unknown, + unknown + >({ + resultsMergeFn: (state, item) => + state.set(item.id.toString(), { + ...item, + foo: 'bar'.repeat(item.id), + }), + }) + reducer = result[0] + const newResults = [{ id: 1 }, { id: 2 }, { id: 3 }] + const state = reducer( + { + ...defaultState, + results: OrderedMap() as StateResultsType, + }, + { + type: PaginatedResultsActionKind.NEW_RESULTS, + payload: { results: newResults }, + } + ) + + expect(state.results.toList().toArray()).toStrictEqual([ + { id: 1, foo: 'bar' }, + { id: 2, foo: 'barbar' }, + { id: 3, foo: 'barbarbar' }, + ]) + }) + }) + describe('loadMore', () => { it('should return if there are no results to load more from', () => { const state = reducer( diff --git a/packages/lib/urql/use-paginated-query/paginated-results-reducer.ts b/packages/lib/urql/use-paginated-query/paginated-results-reducer.ts index 7e67f1cdd..ee444dca9 100644 --- a/packages/lib/urql/use-paginated-query/paginated-results-reducer.ts +++ b/packages/lib/urql/use-paginated-query/paginated-results-reducer.ts @@ -14,11 +14,14 @@ export const getPaginatedResultsReducer = < TType extends WithId, TData, TVariables ->( - { pageSize }: GetPaginatedResultsReducerProps = { - pageSize: 20, - } -): GetPaginatedResultsReducerResult => { +>({ + pageSize = 20, + resultsMergeFn = (map, item) => map.set(item.id.toString(), item), +}: GetPaginatedResultsReducerProps = {}): GetPaginatedResultsReducerResult< + TType, + TData, + TVariables +> => { type ReducerState = PaginatedResultsState const defaultPagination: Pagination = { @@ -57,7 +60,7 @@ export const getPaginatedResultsReducer = < const sliceEnd = hasMore ? -1 : undefined const nextResultsPage = results.slice(0, sliceEnd) const newResults = nextResultsPage.reduce( - (map, item) => map.set(item.id.toString(), item), + resultsMergeFn, state.results ) return { diff --git a/packages/lib/urql/use-paginated-query/types.ts b/packages/lib/urql/use-paginated-query/types.ts index 1d1303031..16085361a 100644 --- a/packages/lib/urql/use-paginated-query/types.ts +++ b/packages/lib/urql/use-paginated-query/types.ts @@ -11,10 +11,13 @@ export interface Pagination { take: number } -export type ResultsType = OrderedMap +export type StateResultsType = OrderedMap< + string | number, + TType +> export interface PaginatedResultsState extends UseQueryState { - results: ResultsType + results: StateResultsType fetching: boolean hasMore: boolean pagination: Pagination @@ -36,8 +39,14 @@ export interface PaginatedResultsAction { payload?: PaginatedResultsActionPayload } -export interface GetPaginatedResultsReducerProps { +export type ResultsMergeFn = ( + state: StateResultsType, + results: TType +) => StateResultsType + +export interface GetPaginatedResultsReducerProps { pageSize?: number + resultsMergeFn?: ResultsMergeFn } export type GetPaginatedResultsReducer = Reducer< @@ -67,7 +76,7 @@ export type VariablesWithPagination = TVariables & Pagination export interface UsePaginatedState extends UseQueryState { - results: ResultsType + results: StateResultsType fetching: boolean hasMore: boolean pagination: Pagination @@ -80,7 +89,7 @@ export type UsePaginatedResponse = [ UsePaginatedState, refetch ] -export interface UsePaginationQueryOptions +export interface UsePaginationQueryOptions extends UseQueryArgs { /** * The GraphQL query @@ -102,6 +111,10 @@ export interface UsePaginationQueryOptions * Pagination options */ pagination?: Pagination + /** + * Merge function to use for new results + */ + resultsMergeFn?: ResultsMergeFn } export type WithId = { diff --git a/packages/lib/urql/use-paginated-query/use-paginated-query.ts b/packages/lib/urql/use-paginated-query/use-paginated-query.ts index e4cc69229..6ae7ac68f 100644 --- a/packages/lib/urql/use-paginated-query/use-paginated-query.ts +++ b/packages/lib/urql/use-paginated-query/use-paginated-query.ts @@ -13,13 +13,14 @@ import { } from './types' export const usePaginatedQuery = ( - options: UsePaginationQueryOptions + options: UsePaginationQueryOptions ): UsePaginatedResponse => { - const { query, dataKey, variables, pageSize = 10 } = options + const { query, dataKey, variables, pageSize = 10, resultsMergeFn } = options const [paginatedResultsReducer, { defaultState }] = getPaginatedResultsReducer({ pageSize, + resultsMergeFn, }) const [state, dispatch] = useReducer(paginatedResultsReducer, defaultState)