Skip to content

Commit 3e6c984

Browse files
committed
useFetch: allow passing an object to run to be spread over init
1 parent 63bfebe commit 3e6c984

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,19 @@ const MyComponent = () => {
257257
function clickHandler() {
258258
run(init => ({
259259
...init,
260-
body: JSON.stringify(formValues)
260+
headers: {
261+
...init.headers,
262+
authentication: "..."
263+
}
261264
}))
262265
}
266+
267+
// alternatively, you can also just use an object that will be spread over `init`.
268+
// please note that this is not deep-merged, so you might override properties present in the
269+
// original `init` parameter
270+
function clickHandler2() {
271+
run({ body: JSON.stringify(formValues) })
272+
}
263273
}
264274
```
265275

packages/react-async/src/useAsync.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,17 @@ 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"
150+
? override(init)
151+
: // override is an Event or SyntheticEvent - do not spread
152+
"preventDefault" in override
153+
? init
154+
: // otherwise, spread override over init
155+
{ ...init, ...override }),
156+
})
147157
: (_, { signal }) => doFetch(input, { signal, ...init }),
148158
[isDefer, JSON.stringify(input), JSON.stringify(init)]
149159
),

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

Lines changed: 32 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,35 @@ describe("useFetch", () => {
178178
expect.objectContaining({ method: "POST", signal: abortCtrl.signal, body: '{"name":"test"}' })
179179
)
180180
})
181+
182+
test("calling `run` with an object as argument allows to override `init` parameters", () => {
183+
const component = (
184+
<Fetch input="/test" init={{ method: "POST" }}>
185+
{({ run }) => <button onClick={() => run({ body: '{"name":"test"}' })}>run</button>}
186+
</Fetch>
187+
)
188+
const { getByText } = render(component)
189+
expect(globalScope.fetch).not.toHaveBeenCalled()
190+
fireEvent.click(getByText("run"))
191+
expect(globalScope.fetch).toHaveBeenCalledWith(
192+
"/test",
193+
expect.objectContaining({ method: "POST", signal: abortCtrl.signal, body: '{"name":"test"}' })
194+
)
195+
})
196+
197+
test("passing `run` directly as a click handler will not spread the event over init", () => {
198+
const component = (
199+
<Fetch input="/test" init={{ method: "POST" }}>
200+
{({ run }) => <button onClick={run}>run</button>}
201+
</Fetch>
202+
)
203+
const { getByText } = render(component)
204+
expect(globalScope.fetch).not.toHaveBeenCalled()
205+
fireEvent.click(getByText("run"))
206+
expect(globalScope.fetch).toHaveBeenCalledWith("/test", expect.any(Object))
207+
expect(globalScope.fetch).not.toHaveBeenCalledWith(
208+
"/test",
209+
expect.objectContaining({ preventDefault: expect.any(Function) })
210+
)
211+
})
181212
})

0 commit comments

Comments
 (0)