skip to Main Content

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


  1. 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.

    Login or Signup to reply.
  2. 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:

    {data.id && <span>{data.id}</span>}
    

    Change to:

    {data && data.id && <span>{data.id}</span>}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search