mirror of
https://github.com/simoneb/axios-hooks.git
synced 2025-12-08 21:25:56 +00:00
Merge pull request #380 from vmlopezr/manual-cancel-example
feature(manual cancellation update): Reset loading state when outstanding call is cancelled
This commit is contained in:
commit
2b7d2cfceb
@ -5,7 +5,8 @@ import { dequal as deepEqual } from 'dequal/lite'
|
||||
|
||||
const actions = {
|
||||
REQUEST_START: 'REQUEST_START',
|
||||
REQUEST_END: 'REQUEST_END'
|
||||
REQUEST_END: 'REQUEST_END',
|
||||
REQUEST_CANCELED: 'REQUEST_CANCELED'
|
||||
}
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
@ -153,6 +154,8 @@ export function makeUseAxios(configureOptions) {
|
||||
...(action.error ? {} : { data: action.payload.data }),
|
||||
[action.error ? 'error' : 'response']: action.payload
|
||||
}
|
||||
case actions.REQUEST_CANCELED:
|
||||
return { ...state, loading: false }
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,8 +188,9 @@ export function makeUseAxios(configureOptions) {
|
||||
} catch (err) {
|
||||
if (!StaticAxios.isCancel(err)) {
|
||||
dispatch({ type: actions.REQUEST_END, payload: err, error: true })
|
||||
} else {
|
||||
dispatch({ type: actions.REQUEST_CANCELED })
|
||||
}
|
||||
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,7 +408,8 @@ function standardTests(
|
||||
|
||||
result.current[2]()
|
||||
|
||||
expect(cancel).toHaveBeenCalled()
|
||||
expect(cancel).toHaveBeenCalledTimes(1)
|
||||
expect(result.current[0].loading).toBe(false)
|
||||
})
|
||||
|
||||
it('should cancel the outstanding request when the component refetches due to a rerender', async () => {
|
||||
@ -485,6 +486,7 @@ function standardTests(
|
||||
result.current[2]()
|
||||
|
||||
expect(cancel).toHaveBeenCalled()
|
||||
expect(result.current[0].loading).toBe(false)
|
||||
})
|
||||
|
||||
it('should not dispatch an error when the request is canceled', async () => {
|
||||
@ -495,18 +497,45 @@ function standardTests(
|
||||
.fn()
|
||||
.mockImplementationOnce(err => err === cancellation)
|
||||
|
||||
const { result, waitFor } = setup('')
|
||||
const { result, waitForNextUpdate } = setup('')
|
||||
|
||||
// if we cancel we won't dispatch the error, hence there's no state update
|
||||
// to wait for. yet, if we don't try to wait, we won't know if we're handling
|
||||
// the error properly because the return value will not have the error until a
|
||||
// state update happens. it would be great to have a better way to test this
|
||||
await waitFor(
|
||||
() => {
|
||||
expect(result.current[0].error).toBeNull()
|
||||
},
|
||||
{ timeout: 1000, suppressErrors: false }
|
||||
)
|
||||
await waitForNextUpdate()
|
||||
expect(result.current[0].error).toBeNull()
|
||||
})
|
||||
|
||||
it('should return previous state after cancel', async () => {
|
||||
const response = { data: 'whatever' }
|
||||
|
||||
const cancellation = new Error('canceled')
|
||||
|
||||
axios.isCancel = jest
|
||||
.fn()
|
||||
.mockImplementationOnce(err => err === cancellation)
|
||||
|
||||
axios
|
||||
.mockResolvedValueOnce(response)
|
||||
.mockRejectedValueOnce(cancellation)
|
||||
|
||||
const { result, waitForNextUpdate, rerender } = setup('', {
|
||||
manual: true
|
||||
})
|
||||
|
||||
act(() => {
|
||||
result.current[1]()
|
||||
})
|
||||
|
||||
await waitForNextUpdate()
|
||||
|
||||
rerender({ config: 'test', options: { manual: false } })
|
||||
|
||||
result.current[2]()
|
||||
|
||||
await waitForNextUpdate()
|
||||
|
||||
expect(axios).toHaveBeenCalledTimes(2)
|
||||
expect(result.current[0].error).toBeNull()
|
||||
expect(result.current[0].loading).toBe(false)
|
||||
expect(result.current[0].response).toBe(response)
|
||||
})
|
||||
})
|
||||
|
||||
@ -580,7 +609,28 @@ function standardTests(
|
||||
|
||||
result.current[2]()
|
||||
|
||||
expect(cancel).toHaveBeenCalled()
|
||||
expect(cancel).toHaveBeenCalledTimes(1)
|
||||
expect(result.current[0].loading).toBe(false)
|
||||
})
|
||||
|
||||
it('should cancel manual request when the config options change', async () => {
|
||||
axios.mockResolvedValue({ data: 'whatever' })
|
||||
|
||||
const { result, waitForNextUpdate, rerender } = setup('', {
|
||||
manual: true
|
||||
})
|
||||
|
||||
act(() => {
|
||||
result.current[1]()
|
||||
})
|
||||
|
||||
rerender({ config: 'new url', options: { manual: true } })
|
||||
|
||||
await waitForNextUpdate()
|
||||
|
||||
expect(result.current[0].loading).toBe(false)
|
||||
expect(cancel).toHaveBeenCalledTimes(1)
|
||||
expect(axios).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should throw an error when the request is canceled', async () => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user