2 years ago

#19761

test-img

Dashiell Rose Bark-Huss

React not rendering element if async call for data takes too long

I'm grabbing user data from an API. The API call takes a while. But even when the frontend gets the response, React never finishes rendering the component.

I can replicate this behavior with setTimeout. A small timeout like 7ms will work, but if I use a larger timeout like 700ms <h1>Text rendered!</h1> doesn't display.

  useEffect(() => {
      setTimeout(() => setUsers({ data: ["user1", "user2", "user3"] }), 700);
  }, []);

In the debugger I can see that the flow seems to be working

  1. The frontend receives the response, and calls setUser.
  2. This triggers the second useEffect callback which updates users.
  3. This re-renders the component, and users && users.updated is true, but then <h1>Text rendered!</h1> doesn't render for some reason.

Oddly though, on codesandbox, I get completely different behavior: <h1>Text rendered!</h1> never renders, even if I use a small timeout like 1ms, or even if I just use setUsers with no setTimeout. And on my local environment, sometimes 700ms does work if I step through it in the debugger slowly but I can't always replicate this.

What's going on? How can I get {users && users.updated && <h1>Text rendered!</h1>} to render properly on longer asynchronous calls?

Full code:

import React, { useEffect, useState } from "react";
export default function App() {
  const [users, setUsers] = useState(null);

  // 1. Get Data from API
  useEffect(() => {
      //----replicating asyncronous API call----
      //"Text rendered!" doesn't render if the timeout is large (700ms)
      //but does render if timeout is small (2ms)
      //(On codesandbox "Text rendered!" never renders, even if you don't use a timeout just use setUsers)
     
      setTimeout(() => setUsers({ data: ["user1", "user2", "user3"] }), 2);
  }, []);

  // 2. Once Data is Receive from API, Transform It
  useEffect(() => {
    if (users) {
      const usersCopy = users;

      usersCopy.updated = true;

      setUsers(usersCopy);
    }
  }, [users]);

  // 3. After the Data is Transformed, Render "Text Rendered!" 
  return (
    <>
      Render text below:
      {users && users.updated && <h1>Text rendered!</h1>}
    </>
  );
}

javascript

reactjs

asynchronous

codesandbox

0 Answers

Your Answer

Accepted video resources