Skip to content

Commit bae616c

Browse files
committed
useFetch: allow passing an object to run to be spread over init
1 parent ec58f61 commit bae616c

File tree

3 files changed

+61
-4
lines changed

3 files changed

+61
-4
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,19 @@ const MyComponent = () => {
197197
function clickHandler() {
198198
run(init => ({
199199
...init,
200-
body: JSON.stringify(formValues)
200+
headers: {
201+
...init.headers,
202+
authentication: "..."
203+
}
201204
}))
202205
}
206+
207+
// alternatively, you can also just use an object that will be spread over `init`.
208+
// please note that this is not deep-merged, so you might override properties present in the
209+
// original `init` parameter
210+
function clickHandler2() {
211+
run({ body: JSON.stringify(formValues) })
212+
}
203213
}
204214
```
205215

packages/react-async/src/useAsync.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useCallback, useDebugValue, useEffect, useMemo, useRef, useReducer } fr
33
import globalScope from "./globalScope"
44
import { actionTypes, init, dispatchMiddleware, reducer as asyncReducer } from "./reducer"
55

6-
const noop = () => {}
6+
const noop = () => { }
77

88
const useAsync = (arg1, arg2) => {
99
const options = typeof arg1 === "function" ? { ...arg2, promiseFn: arg1 } : arg1
@@ -143,7 +143,16 @@ const useAsyncFetch = (input, init, { defer, json, ...options } = {}) => {
143143
[fn]: useCallback(
144144
isDefer
145145
? ([override], _, { signal }) =>
146-
doFetch(input, { signal, ...(typeof override === "function" ? override(init) : init) })
146+
doFetch(input, {
147+
signal, ...(
148+
// override is a function, call it with init
149+
typeof override === "function" ? override(init)
150+
// override is an Event or SyntheticEvent - do not spread
151+
: 'preventDefault' in override ? init
152+
// otherwise, spread override over init
153+
: { ...init, ...override }
154+
)
155+
})
147156
: (_, { signal }) => doFetch(input, { signal, ...init }),
148157
[isDefer, JSON.stringify(input), JSON.stringify(init)]
149158
),

packages/react-async/src/useAsync.spec.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ describe("useFetch", () => {
162162
expect(json).toHaveBeenCalled()
163163
})
164164

165-
test("calling `run` with an argument allows to override `init` parameters", () => {
165+
test("calling `run` with a method argument allows to override `init` parameters", () => {
166166
const component = (
167167
<Fetch input="/test" init={{ method: "POST" }}>
168168
{({ run }) => (
@@ -178,4 +178,42 @@ describe("useFetch", () => {
178178
expect.objectContaining({ method: "POST", signal: abortCtrl.signal, body: '{"name":"test"}' })
179179
)
180180
})
181+
182+
183+
test("calling `run` with an object as argument allows to override `init` parameters", () => {
184+
const component = (
185+
<Fetch input="/test" init={{ method: "POST" }}>
186+
{({ run }) => (
187+
<button onClick={() => run({ body: '{"name":"test"}' })}>run</button>
188+
)}
189+
</Fetch>
190+
)
191+
const { getByText } = render(component)
192+
expect(globalScope.fetch).not.toHaveBeenCalled()
193+
fireEvent.click(getByText("run"))
194+
expect(globalScope.fetch).toHaveBeenCalledWith(
195+
"/test",
196+
expect.objectContaining({ method: "POST", signal: abortCtrl.signal, body: '{"name":"test"}' })
197+
)
198+
})
199+
200+
201+
test("passing `run` directly as a click handler will not spread the event over init", () => {
202+
const component = (
203+
<Fetch input="/test" init={{ method: "POST" }}>
204+
{({ run }) => (<button onClick={run}>run</button>)}
205+
</Fetch >
206+
)
207+
const { getByText } = render(component)
208+
expect(globalScope.fetch).not.toHaveBeenCalled()
209+
fireEvent.click(getByText("run"))
210+
expect(globalScope.fetch).toHaveBeenCalledWith(
211+
"/test",
212+
expect.any(Object)
213+
);
214+
expect(globalScope.fetch).not.toHaveBeenCalledWith(
215+
"/test",
216+
expect.objectContaining({ preventDefault: expect.any(Function) })
217+
)
218+
})
181219
})

0 commit comments

Comments
 (0)