Home > Blockchain >  Load async data before rendering the DOM
Load async data before rendering the DOM

Time:03-12

Still learning, and I have an issue understanding how I can get the data from an async function then show it in the DOM.

Indeed, I'm getting undefined, since the dom renders before the async function.

I'm stuck and my question is how to manage this situation ? What's the good practice ?

export default function ProductCard ({ product }) {

    const { handle, title } = product.node

    const [productDetails, setProductDetails] = useState();

    const data = async () => {
        const data = await getProduct(handle)
        //console.log(data)
        setProductDetails(data);
    }

    useEffect(() => {
        data();
    }, [])

//or data();

console.log("productDetails", productDetails);


return (
    <>
       {productDetails.handle}
    </>
)


}

Thanks for the help and support.

CodePudding user response:

You're close. It's normal for the first render to have undefined for the state, since that's what you've set the initial state to, and it takes time to get the data. So you just need to render something different for the case where you don't have data yet. You can return null if you want to render nothing, or perhaps a loading placeholder:

if (productDetails) {
  return (
    <>
      {productDetails.handle}
    </>
  )
} else {
  return <div>Loading...</div>
  // or
  //return null;
}

For your case, that should be enough. But if you ever find yourself working with a really complicated component, where always having to check for undefined is combersome, then you could split it into two components. The outer component does the loading and handles the possibility of undefined, and the inner component only gets rendered once undefined is no longer possible:

const Parent = (props) => {
  const [productDetails, setProductDetails] = useState();

  useEffect(() => {
    const fetchData = async () => {
      const data = await getProduct(handle);
      //console.log(data)
      setProductDetails(data);
    };
    fetchData();
  }, []);

  if (productDetails) {
    return <Child {...props} productDetails={productDetails} />;
  } else {
    return null;
  }
};

const Child = ({ product, productDetails }) => {
  // Everything in here can assume productDetails exists

  return (
    <>
      {productDetails.handle}
    </>
  )
};

  • Related