Skip to content

Commit

Permalink
Merge pull request #2844 from reduxjs/bugfix/forceRefetch-obj-args
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson committed Oct 30, 2022
2 parents 270a14f + db3ed1e commit d934fad
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 1 deletion.
8 changes: 7 additions & 1 deletion packages/toolkit/src/query/react/buildHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import type { UninitializedValue } from './constants'
import { UNINITIALIZED_VALUE } from './constants'
import { useShallowStableValue } from './useShallowStableValue'
import type { BaseQueryFn } from '../baseQueryTypes'
import { defaultSerializeQueryArgs } from '../defaultSerializeQueryArgs'

// Copy-pasted from React-Redux
export const useIsomorphicLayoutEffect =
Expand Down Expand Up @@ -688,7 +689,12 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
const dispatch = useDispatch<ThunkDispatch<any, any, AnyAction>>()
const stableArg = useStableQueryArgs(
skip ? skipToken : arg,
serializeQueryArgs,
// Even if the user provided a per-endpoint `serializeQueryArgs` with
// a consistent return value, _here_ we want to use the default behavior
// so we can tell if _anything_ actually changed. Otherwise, we can end up
// with a case where the query args did change but the serialization doesn't,
// and then we never try to initiate a refetch.
defaultSerializeQueryArgs,
context.endpointDefinitions[name],
name
)
Expand Down
60 changes: 60 additions & 0 deletions packages/toolkit/src/query/tests/buildHooks.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ import { delay } from '../../utils'
// This can be used to test how many renders happen due to data changes or
// the refetching behavior of components.
let amount = 0
let nextItemId = 0

interface Item {
id: number
}

const api = createApi({
baseQuery: async (arg: any) => {
Expand All @@ -54,6 +59,15 @@ const api = createApi({
}
}

if (arg?.body && 'listItems' in arg.body) {
const items: Item[] = []
for (let i = 0; i < 3; i++) {
const item = { id: nextItemId++ }
items.push(item)
}
return { data: items }
}

return {
data: arg?.body ? { ...arg.body, ...(amount ? { amount } : {}) } : {},
}
Expand Down Expand Up @@ -85,6 +99,23 @@ const api = createApi({
getError: build.query({
query: (query) => '/error',
}),
listItems: build.query<Item[], { pageNumber: number }>({
serializeQueryArgs: ({ endpointName }) => {
return endpointName
},
query: ({ pageNumber }) => ({
url: `items?limit=1&offset=${pageNumber}`,
body: {
listItems: true,
},
}),
merge: (currentCache, newItems) => {
currentCache.push(...newItems)
},
forceRefetch: ({ currentArg, previousArg }) => {
return true
},
}),
}),
})

Expand Down Expand Up @@ -589,6 +620,35 @@ describe('hooks tests', () => {
)
})

test(`useQuery refetches when query args object changes even if serialized args don't change`, async () => {
function ItemList() {
const [pageNumber, setPageNumber] = React.useState(0)
const { data = [] } = api.useListItemsQuery({ pageNumber })

const renderedItems = data.map((item) => (
<li key={item.id}>ID: {item.id}</li>
))
return (
<div>
<button onClick={() => setPageNumber(pageNumber + 1)}>
Next Page
</button>
<ul>{renderedItems}</ul>
</div>
)
}

render(<ItemList />, { wrapper: storeRef.wrapper })

await screen.findByText('ID: 0')

await act(async () => {
screen.getByText('Next Page').click()
})

await screen.findByText('ID: 3')
})

describe('api.util.resetApiState resets hook', () => {
test('without `selectFromResult`', async () => {
const { result } = renderHook(() => api.endpoints.getUser.useQuery(5), {
Expand Down

0 comments on commit d934fad

Please sign in to comment.