Skip to content

Commit

Permalink
feat: default options
Browse files Browse the repository at this point in the history
  • Loading branch information
simoneb committed Jan 13, 2021
1 parent 27c290d commit b218e68
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 18 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ function App() {
### API

- [useAxios](#useaxiosurlconfig-options)
- [configure](#configure-cache-axios-)
- [configure](#configure-cache-axios-defaultoptions)
- [serializeCache](#serializeCache)
- [loadCache](#loadcachecache)
- [makeUseAxios](#makeuseaxios-cache-axios-)
- [makeUseAxios](#makeuseaxios-cache-axios-defaultoptions)

### Examples

Expand Down Expand Up @@ -92,6 +92,7 @@ The main React hook to execute HTTP requests.
- `options` - An options object.
- `manual` ( `false` ) - If true, the request is not executed immediately. Useful for non-GET requests that should not be executed when the component renders. Use the `execute` function returned when invoking the hook to execute the request manually.
- `useCache` ( `true` ) - Allows caching to be enabled/disabled for the hook. It doesn't affect the `execute` function returned by the hook.
- `ssr` ( `true` ) - Enables or disables SSR support

**Returns**

Expand All @@ -112,12 +113,13 @@ The main React hook to execute HTTP requests.

A promise containing the response. If the request is unsuccessful, an exception is thrown and must be handled manually.

### configure({ cache, axios })
### configure({ cache, axios, defaultOptions })

Allows to provide custom instances of cache and axios.
Allows to provide custom instances of cache and axios and to override the default options.

- `cache` An instance of [lru-cache](https://github.com/isaacs/node-lru-cache), or `false` to disable the cache
- `axios` An instance of [axios](https://github.com/axios/axios#creating-an-instance)
- `defaultOptions` An object overriding the default Hook options. It will be merged with the default options.

### serializeCache()

Expand All @@ -133,12 +135,13 @@ Populates the cache with serialized data generated by `serializeCache`.

- `cache` The serializable representation of the request-response cache generated by `serializeCache`

### makeUseAxios({ cache, axios })
### makeUseAxios({ cache, axios, defaultOptions })

Creates an instance of the `useAxios` hook configured with the supplied cache and axios instance.
Creates an instance of the `useAxios` hook configured with the supplied cache, axios instance and default options.

- `cache` An instance of [lru-cache](https://github.com/isaacs/node-lru-cache), or `false` to disable the cache
- `axios` An instance of [axios](https://github.com/axios/axios#creating-an-instance)
- `defaultOptions` An object overriding the default Hook options. It will be merged with the default options.

**Returns**

Expand All @@ -159,6 +162,7 @@ Unless provided via the `configure` function, `axios-hooks` uses as defaults:

- `axios` - the default `axios` package export
- `cache` - a new instance of the default `lru-cache` package export, with no arguments
- `defaultOptions` - `{ manual: false, useCache: true, ssr: true }`

These defaults may not suit your needs, for example:

Expand Down
4 changes: 3 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface ResponseValues<TResponse, TError> {
export interface Options {
manual?: boolean
useCache?: boolean
ssr?: boolean
}

export interface RefetchOptions {
Expand All @@ -27,6 +28,7 @@ export interface RefetchOptions {
export interface ConfigureOptions {
axios?: AxiosInstance | AxiosStatic | any
cache?: LRUCache<any, any> | false
defaultOptions?: Options
}

export interface UseAxios {
Expand Down Expand Up @@ -66,4 +68,4 @@ export function resetConfigure(): void
// private
export const __ssrPromises: Promise<any>[]

export function makeUseAxios(options: ConfigureOptions): UseAxios
export function makeUseAxios(options?: ConfigureOptions): UseAxios
20 changes: 16 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ const actions = {
REQUEST_END: 'REQUEST_END'
}

const DEFAULT_OPTIONS = {
manual: false,
useCache: true,
ssr: true
}

const useAxios = makeUseAxios()

const {
Expand Down Expand Up @@ -50,15 +56,17 @@ function configToObject(config) {
return config
}

export function makeUseAxios(configurationOptions) {
export function makeUseAxios(configureOptions) {
let cache
let axiosInstance
let defaultOptions

const __ssrPromises = []

function resetConfigure() {
cache = new LRU()
axiosInstance = StaticAxios
defaultOptions = DEFAULT_OPTIONS
}

function configure(options = {}) {
Expand All @@ -69,10 +77,14 @@ export function makeUseAxios(configurationOptions) {
if (options.cache !== undefined) {
cache = options.cache
}

if (options.defaultOptions !== undefined) {
defaultOptions = { ...DEFAULT_OPTIONS, ...options.defaultOptions }
}
}

resetConfigure()
configure(configurationOptions)
configure(configureOptions)

function loadCache(data) {
cache.load(data)
Expand Down Expand Up @@ -193,7 +205,7 @@ export function makeUseAxios(configurationOptions) {
)

options = React.useMemo(
() => ({ manual: false, useCache: true, ...options }),
() => ({ ...defaultOptions, ...options }),
// eslint-disable-next-line react-hooks/exhaustive-deps
[JSON.stringify(options)]
)
Expand All @@ -205,7 +217,7 @@ export function makeUseAxios(configurationOptions) {
createInitialState(config, options)
)

if (typeof window === 'undefined' && !options.manual) {
if (typeof window === 'undefined' && options.ssr && !options.manual) {
useAxios.__ssrPromises.push(axiosInstance(config))
}

Expand Down
80 changes: 78 additions & 2 deletions test/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('makeUseAxios', () => {
})

it('should not throw', () => {
expect(makeUseAxios({})).toBeTruthy()
expect(makeUseAxios()).toBeTruthy()
})

it('should provide a custom implementation of axios', () => {
Expand Down Expand Up @@ -107,8 +107,48 @@ describe('makeUseAxios', () => {
})
})

describe('default hook options', () => {
describe('manual', () => {
it('should override default manual option', () => {
const setup = makeSetup(
makeUseAxios({ defaultOptions: { manual: true } })
)

setup()

expect(axios).not.toHaveBeenCalled()
})
})

describe('useCache', () => {
it('should override default useCache option', async () => {
const setup = makeSetup(
makeUseAxios({ defaultOptions: { useCache: false } })
)

axios.mockResolvedValue({ data: 'whatever' })

const { waitForNextUpdate, unmount } = setup()

await waitForNextUpdate()

unmount()

await setup().waitForNextUpdate()

expect(axios).toHaveBeenCalledTimes(2)
})
})

describe('ssr', () => {
it('should be able to set ssr option', () => {
makeSetup(makeUseAxios({ defaultOptions: { ssr: false } }))
})
})
})

describe('standard tests', () => {
const useAxios = makeUseAxios({})
const useAxios = makeUseAxios()

standardTests(
useAxios,
Expand Down Expand Up @@ -942,6 +982,42 @@ function standardTests(
expect(axios).toHaveBeenCalledTimes(2)
})
})

describe('default hook options', () => {
describe('manual', () => {
it('should override default manual option', () => {
configure({ defaultOptions: { manual: true } })

setup()

expect(axios).not.toHaveBeenCalled()
})
})

describe('useCache', () => {
it('should override default useCache option', async () => {
configure({ defaultOptions: { useCache: false } })

axios.mockResolvedValue({ data: 'whatever' })

const { waitForNextUpdate, unmount } = setup()

await waitForNextUpdate()

unmount()

await setup().waitForNextUpdate()

expect(axios).toHaveBeenCalledTimes(2)
})
})

describe('ssr', () => {
it('should be able to set ssr option', () => {
configure({ defaultOptions: { ssr: false } })
})
})
})
})

describe('loadCache', () => {
Expand Down
19 changes: 14 additions & 5 deletions test/index.test.ssr.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import axios from 'axios'
import React from 'react'
import ReactDOM from 'react-dom/server'

import useAxios, { __ssrPromises } from '../src'
import { makeUseAxios } from '../src'
import { mockCancelToken } from './testUtils'

jest.mock('axios')

let useAxios

beforeEach(() => {
mockCancelToken(axios)
useAxios = makeUseAxios()
})

function DummyComponent(props) {
Expand All @@ -17,16 +20,22 @@ function DummyComponent(props) {
return null
}

it('should not populate promises on server when manual', () => {
it('should not populate promises on server when manual=true', () => {
ReactDOM.renderToString(<DummyComponent manual={true} />)

expect(__ssrPromises.length).toBe(0)
expect(useAxios.__ssrPromises.length).toBe(0)
})

it('should not populate promises on server when ssr=false', () => {
ReactDOM.renderToString(<DummyComponent ssr={false} />)

expect(useAxios.__ssrPromises.length).toBe(0)
})

it('should populate promises on server', () => {
it('should populate promises on server with default options', () => {
axios.mockResolvedValueOnce({ data: 'whatever' })

ReactDOM.renderToString(<DummyComponent />)

expect(__ssrPromises.length).toBe(1)
expect(useAxios.__ssrPromises.length).toBe(1)
})

0 comments on commit b218e68

Please sign in to comment.