React Hooks: how to wait for the data to be fetched before rendering

Viewed 13775

I have fetch method in useEffect hook:


export const CardDetails = () => {
  const [ card, getCardDetails ] = useState();

  const { id } = useParams();

  useEffect(() => {
    fetch(`http://localhost:3001/cards/${id}`)
    .then((res) => res.json())
    .then((data) => getCardDetails(data))
  }, [id])

  return (
     <DetailsRow data={card} />
  )
}

But then inside DetailsRow component this data is not defined, which means that I render this component before data is fetched. How to solve it properly?

3 Answers

Just don't render it when the data is undefined:

export const CardDetails = () => {
  const [card, setCard] = useState();

  const { id } = useParams();

  useEffect(() => {
    fetch(`http://localhost:3001/cards/${id}`)
      .then((res) => res.json())
      .then((data) => setCard(data));
  }, [id]);

  if (card === undefined) {
    return <>Still loading...</>;
  }

  return <DetailsRow data={card} />;
};

There are 3 ways to not render component if there aren't any data yet.

  1. {data && <Component data={data} />}
  2. Check if(!data) { return null } before render. This method will prevent All component render until there aren't any data.
  3. Use some <Loading /> component and ternar operator inside JSX. In this case you will be able to render all another parts of component which are not needed data -> {data ? <Component data={data} /> : <Loading>}

Try this:

export const CardDetails = () => {
    const [card, getCardDetails] = useState();
    const { id } = useParams();
    useEffect(() => {
        if (!data) {
            fetch(`http://localhost:3001/cards/${id}`)
                .then((res) => res.json())
                .then((data) => getCardDetails(data))
        }
    }, [id, data]);
    return (
        <div>
            {data && <DetailsRow data={card} />}
            {!data && <p>loading...</p>}
        </div>
    );
};
Related