ama
ama copied to clipboard
How to handle sequenced ajax call with hook
Hi Kent, I need any suggestion on how to handle sequenced ajax call with custom hooks.
I made a rude custom useFetch hook that handle only simple GET requests that is something like this
function useFetch(url) {
const [data, setData] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
fetch(url)
.then((data) => data.json())
.then(data => {
setData(data)
setLoading(false)
})
.catch((err) => {
setErr(err.toString())
setLoading(false)
})
}, [url])
return [loading, error, data]
}
I want to handle 2 consecutive fetch in wich the second one is based on the first response,
function Comp(props) {
const [loading1, error1, data1] = useFetch("url1")
const [loading2, error2, data2] = useFetch(`url2/${data1.id}`)
return (
..something using data2
)
}
The problem of course is that hooks are asyncronous, so the second useFetch runs before the first get finished, so i cannot use the data coming back in the second useFetch... So I ended up by splitting that in 2 nested components like so
function Comp1(props) {
const [loading, error, data] = useFetch("url1")
return data ? (
<Comp2 dataid={data.id}/>
) : null
}
function Comp2(props) {
const [loading, error, data] = useFetch(`url2/${props.dataId}`)
return (
..something using data
)
}
But it's seems weird, something like an hack... Any Idea?
Thank you
Hi @shall-git
It's maybe a bit unfamiliar, give it some time.
This is actually a really cool pattern, <Comp1>
only renders the <Comp2>
if props.dataId
is set.
This is pretty good component encapsulation. However it could be more durable; the key here is avoiding tight-coupling. E.g. where <Comp2> relies on logic in <Comp1> to avoid errors.
Here's one way to make <Comp2>
more durable against errors:
function Comp2(props) {
// TIP: Here's how I'd implement a low-ceremony way to avoid rendering invalid state/props.
if (!props.dataId) return <div>For details, please make a selection</div>
const [loading, error, data] = useFetch(`url2/${props.dataId}`)
return (
..something using data
)
}
Btw, thanks @kentcdodds for all you do! 👍
Thanks for the question @shall-git!
Note @justsml, your solution there breaks the rules of hooks by making useFetch
conditionally called due to the if
statement.
I'm actually ok with the "hack" mentioned by @shall-git, but I show a few other ways to solve the problem in today's DevTipsWithKent video: https://www.youtube.com/watch?v=y55rLsSNUiM&index=2&list=PLV5CVI1eNcJgCrPH_e6d57KRUTiDZgs0u&t=0s
Here's my solution: https://codesandbox.io/s/0owknqvzmn
Here's my Suspense solution: https://codesandbox.io/s/84jkm1p0wj (NOTE: DO NOT USE THE SUSPENSE SOLUTION AS IT IS SERIOUSLY FLAWED AND SUSPENSE IS NOT READY FOR DATA FETCHING, BUT IT IS SUPER COOL RIGHT!?)
I hope that's helpful!
@kentcdodds thanks for the clarification! Hooks are making me re-think components in such interesting ways.
Great video as always!
Is that reducer pattern you mentioned in the link? Or did i miss it in the video?
Here's how I would write the reducer version of that: https://codesandbox.io/s/m58yn540j8
Note: there's more work to do there to cancel requests etc. But that's a good starting point.
Great educative answer as always @kentcdodds . I'm just wondering if we can somehow justify beginning to use react-cache and suspense for data fetching in production today. What do we know about the public "api" that will for sure not change, and would it really be that risky to just start using https://github.com/facebook/react/tree/master/packages/react-cache and accepting the fact that minor changes to the api will most likely occur. I mean, last official warnings about using it was from mid february - does anyone have some inside info on whether the implementation is almost done or if it will be completely different in the end? We're in the process of rewriting a large app, and I really would like to handle cache, fetch and rendering of data as close as possible to the expected final solution. If using the react-cache is too risky right now, would something like https://github.com/CharlesStover/fetch-suspense make sense or do you see any problems with using it?
I strongly recommend against trying to use suspense for data fetching before the react team says it's ready. Don't do it.
Thanks for the question @shall-git!
Note @justsml, your solution there breaks the rules of hooks by making
useFetch
conditionally called due to theif
statement.I'm actually ok with the "hack" mentioned by @shall-git, but I show a few other ways to solve the problem in today's DevTipsWithKent video: https://www.youtube.com/watch?v=y55rLsSNUiM&index=2&list=PLV5CVI1eNcJgCrPH_e6d57KRUTiDZgs0u&t=0s
Here's my solution: https://codesandbox.io/s/0owknqvzmn
Here's my Suspense solution: https://codesandbox.io/s/84jkm1p0wj (NOTE: DO NOT USE THE SUSPENSE SOLUTION AS IT IS SERIOUSLY FLAWED AND SUSPENSE IS NOT READY FOR DATA FETCHING, BUT IT IS SUPER COOL RIGHT!?)
I hope that's helpful!
How would you test this?
Good question @mpcen. I'll see about giving you an answer eventually :)
Good question @mpcen. I'll see about giving you an answer eventually :)
Looking forward to it!