diff --git a/README.md b/README.md index 4932d072..31a42280 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ function App() { - [Pagination](https://codesandbox.io/s/axios-hooks-pagination-1wk3u) - [Infinite scrolling](https://codesandbox.io/s/axios-hooks-infinite-scrolling-42nw6) - [Request chaining](https://codesandbox.io/s/axios-hooks-request-chaining-wn12l) +- [Options change detection](https://codesandbox.io/s/axios-hooks-options-change-v23tl) - [react-native](https://snack.expo.io/@simoneb/axios-hooks-react-native) - [With react-sortable-hoc](https://codesandbox.io/s/axios-hooks-react-sortable-hoc-eo3oy) - [With react-router](https://codesandbox.io/s/axios-hooks-react-router-26iwm) diff --git a/src/index.js b/src/index.js index 31ea1b2e..c5ecaf93 100644 --- a/src/index.js +++ b/src/index.js @@ -186,11 +186,17 @@ export function makeUseAxios(configurationOptions) { } function useAxios(config, options) { - config = configToObject(config) - - const stringifiedConfig = JSON.stringify(config) + config = React.useMemo( + () => configToObject(config), + // eslint-disable-next-line react-hooks/exhaustive-deps + [JSON.stringify(config)] + ) - options = { manual: false, useCache: true, ...options } + options = React.useMemo( + () => ({ manual: false, useCache: true, ...options }), + // eslint-disable-next-line react-hooks/exhaustive-deps + [JSON.stringify(options)] + ) const cancelSourceRef = React.useRef() @@ -228,8 +234,7 @@ export function makeUseAxios(configurationOptions) { } return cancelOutstandingRequest - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [stringifiedConfig]) + }, [config, options, withCancelToken, cancelOutstandingRequest]) const refetch = React.useCallback( (configOverride, options) => { @@ -244,8 +249,7 @@ export function makeUseAxios(configurationOptions) { dispatch ) }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [stringifiedConfig] + [config, withCancelToken] ) return [state, refetch] diff --git a/test/index.test.jsx b/test/index.test.jsx index 2d130dda..36add3bb 100644 --- a/test/index.test.jsx +++ b/test/index.test.jsx @@ -695,7 +695,7 @@ function standardTests( }) }) - describe('manual requests', () => { + describe('manual option', () => { it('should set loading to false on initial render', async () => { const { result } = setup('', { manual: true }) @@ -834,6 +834,68 @@ function standardTests( }) }) + describe('option change detection', () => { + it('manual:false to manual:true with cache disabled should execute first request only', async () => { + axios.mockResolvedValue({ data: 'whatever' }) + + const { waitForNextUpdate, rerender } = setup('', { + manual: false, + useCache: false + }) + + await waitForNextUpdate() + + rerender({ config: '', options: { manual: true } }) + + expect(axios).toHaveBeenCalledTimes(1) + }) + + it('manual:true to manual:false with cache disabled should execute second request only', async () => { + axios.mockResolvedValue({ data: 'whatever' }) + + const { waitForNextUpdate, rerender } = setup('', { + manual: true, + useCache: false + }) + + rerender({ config: '', options: { manual: false } }) + + await waitForNextUpdate() + + expect(axios).toHaveBeenCalledTimes(1) + }) + + it('useCache:true to useCache:false should execute both requests', async () => { + axios.mockResolvedValue({ data: 'whatever' }) + + const { waitForNextUpdate, rerender } = setup('', { + useCache: true + }) + + await waitForNextUpdate() + + rerender({ config: '', options: { useCache: false } }) + + await waitForNextUpdate() + + expect(axios).toHaveBeenCalledTimes(2) + }) + + it('useCache:false to useCache:true should execute first request only', async () => { + axios.mockResolvedValue({ data: 'whatever' }) + + const { waitForNextUpdate, rerender } = setup('', { + useCache: false + }) + + await waitForNextUpdate() + + rerender({ config: '', options: { useCache: true } }) + + expect(axios).toHaveBeenCalledTimes(1) + }) + }) + describe('configure', () => { afterEach(() => resetConfigure())