Skip to content

Commit 6f8ab2a

Browse files
committed
useFetch: allow passing an object to run to be spread over init
1 parent 9ef5b86 commit 6f8ab2a

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
@@ -243,9 +243,19 @@ const MyComponent = () => {
243243
function clickHandler() {
244244
run(init => ({
245245
...init,
246-
body: JSON.stringify(formValues)
246+
headers: {
247+
...init.headers,
248+
authentication: "..."
249+
}
247250
}))
248251
}
252+
253+
// alternatively, you can also just use an object that will be spread over `init`.
254+
// please note that this is not deep-merged, so you might override properties present in the
255+
// original `init` parameter
256+
function clickHandler2() {
257+
run({ body: JSON.stringify(formValues) })
258+
}
249259
}
250260
```
251261

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)