Should I rely on useEffect
or componentDidUpdate
to perform async operations as opposed to reacting directly to user events where possible ?
Say I need to send an API request when the user has clicked a button, should I force a re-render and then send the request ? or can I just send the request when the user has clicked ?
const [hasClicked, setClicked] = useState(false)
const [data, setData] = useState({})
useEffect(
async function fetchSomething() {
const fetchedData = await API.getData()
setData(fetchedData)
}
fetchSomething()
, [hasClicked])
return (
<div>
{data.id && <span>{data.id}</span>}
<button onClick={() => setClicked(true)}>Click me</button>
</div>)
vs
const [data, setData] = useState(null)
async function fetchSomething() {
const fetchedData = await API.getData()
setData(fetchedData)
}
return (
<div>
{data.id && <span>{data.id}</span>}
<button onClick={fetchSomething}>Click me</button>
</div>)
(suppose loading
state is handled externally and the button gets disabled when the data fetch already started once)
EDIT:
We don’t want to keep track of state however we saw these articles in which Dan suggests the callback is event handler is handled within useEffect
https://overreacted.io/a-complete-guide-to-useeffect/#speaking-of-race-conditions
https://github.com/facebook/react/issues/14326#issuecomment-472043812
2
Answers
I would only use the first example in case you need to keep track of when the user click the button.
You don’t need to use a state just to call the async function.
If you aren’t going to use
hasClicked
anywhere else, then just use your second example.I don’t see any reason why you would want to re render when the button is clicked, unless you want to visually change the button and indicate it is loading or block further click events.
This line could be problematic if data is null or not defined:
Change to: