Skip to content

Commit

Permalink
🐛 Fix bug with useMutation shared results (reduxjs#1616)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shrugsy committed Oct 16, 2021
1 parent e3379f1 commit 595e283
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 10 deletions.
23 changes: 13 additions & 10 deletions packages/toolkit/src/query/react/buildHooks.ts
Expand Up @@ -825,16 +825,19 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
const originalArgs =
fixedCacheKey == null ? promise?.arg.originalArgs : undefined
const reset = useCallback(() => {
if (promise) {
setPromise(undefined)
} else if (fixedCacheKey) {
dispatch(
api.internalActions.removeMutationResult({
requestId,
fixedCacheKey,
})
)
}
batch(() => {
if (promise) {
setPromise(undefined)
}
if (fixedCacheKey) {
dispatch(
api.internalActions.removeMutationResult({
requestId,
fixedCacheKey,
})
)
}
})
}, [dispatch, fixedCacheKey, promise, requestId])
const finalState = useMemo(
() => ({ ...currentState, originalArgs, reset }),
Expand Down
Expand Up @@ -94,6 +94,79 @@ describe('fixedCacheKey', () => {
expect(getByTestId(c2, 'data').textContent).toBe('')
})

test('resetting from the component that triggered the mutation resets for each shared result', async () => {
render(
<>
<Component name="C1" fixedCacheKey="test-A" />
<Component name="C2" fixedCacheKey="test-A" />
<Component name="C3" fixedCacheKey="test-B" />
<Component name="C4" fixedCacheKey="test-B" />
</>,
{ wrapper: storeRef.wrapper }
)
const c1 = screen.getByTestId('C1')
const c2 = screen.getByTestId('C2')
const c3 = screen.getByTestId('C3')
const c4 = screen.getByTestId('C4')
expect(getByTestId(c1, 'status').textContent).toBe('uninitialized')
expect(getByTestId(c2, 'status').textContent).toBe('uninitialized')
expect(getByTestId(c3, 'status').textContent).toBe('uninitialized')
expect(getByTestId(c4, 'status').textContent).toBe('uninitialized')

// trigger with a component using the first cache key
getByTestId(c1, 'trigger').click()

await waitFor(() =>
expect(getByTestId(c1, 'status').textContent).toBe('fulfilled')
)

// the components with the first cache key should be affected
expect(getByTestId(c1, 'data').textContent).toBe('C1')
expect(getByTestId(c2, 'status').textContent).toBe('fulfilled')
expect(getByTestId(c2, 'data').textContent).toBe('C1')
expect(getByTestId(c2, 'status').textContent).toBe('fulfilled')

// the components with the second cache key should be unaffected
expect(getByTestId(c3, 'data').textContent).toBe('')
expect(getByTestId(c3, 'status').textContent).toBe('uninitialized')
expect(getByTestId(c4, 'data').textContent).toBe('')
expect(getByTestId(c4, 'status').textContent).toBe('uninitialized')

// trigger with a component using the second cache key
getByTestId(c3, 'trigger').click()

await waitFor(() =>
expect(getByTestId(c3, 'status').textContent).toBe('fulfilled')
)

// the components with the first cache key should be unaffected
expect(getByTestId(c1, 'data').textContent).toBe('C1')
expect(getByTestId(c2, 'status').textContent).toBe('fulfilled')
expect(getByTestId(c2, 'data').textContent).toBe('C1')
expect(getByTestId(c2, 'status').textContent).toBe('fulfilled')

// the component with the second cache key should be affected
expect(getByTestId(c3, 'data').textContent).toBe('C3')
expect(getByTestId(c3, 'status').textContent).toBe('fulfilled')
expect(getByTestId(c4, 'data').textContent).toBe('C3')
expect(getByTestId(c4, 'status').textContent).toBe('fulfilled')

// test reset from the component that triggered the mutation for the first cache key
getByTestId(c1, 'reset').click()

// the components with the first cache key should be affected
expect(getByTestId(c1, 'data').textContent).toBe('')
expect(getByTestId(c1, 'status').textContent).toBe('uninitialized')
expect(getByTestId(c2, 'data').textContent).toBe('')
expect(getByTestId(c2, 'status').textContent).toBe('uninitialized')

// the components with the second cache key should be unaffected
expect(getByTestId(c3, 'data').textContent).toBe('C3')
expect(getByTestId(c3, 'status').textContent).toBe('fulfilled')
expect(getByTestId(c4, 'data').textContent).toBe('C3')
expect(getByTestId(c4, 'status').textContent).toBe('fulfilled')
})

test('two mutations with different `fixedCacheKey` do not influence each other', async () => {
render(
<>
Expand Down

0 comments on commit 595e283

Please sign in to comment.