title: How to populate an array before conditional render which is based on the length of the array?
body: <p>I want to populate an array before render, and the render is conditional based on the length of the array.</p>
  
  <p>If the length of the array > 0, do the render, otherwise don't.</p>
  
  <p>But it seems that the length is always 0 becasue <code>useEffect</code> is asynchronous, so the render is never done.</p>
  
  <p>Below is my code:</p>
  
  <pre><code>function OrderDetail(props) {
      const {userInfo} = useSelector(state =&gt; state.user)
      const [order, setOrder] = useState({});
      const [items, setItems] = useState([]);
  
      useEffect(()=&gt;{
          if(!userInfo){
              props.history.push("/")
              return
          }
  
          const fetchOrderAndItems = async () =&gt; {
              // Get an order from backend.
              const order = await axios.get("/api/orders/" + props.match.params.id, {
                  headers:{
                      authorization: "Bearer " + userInfo.token
                  }
              });
              const order_data = order.data
              setOrder(order_data)
  
              // Take out the id of all items in the order, retrieve each product from backend, 
              //push them in "items_array" and set it in the "items" state.
              let items_array = [];
              order_data.orderItems.forEach( async (orderItem) =&gt; {
                  const {data} = await axios.get("/api/products/" + orderItem.productId);
                  items_array.push(data);
              })
  
              console.log("items_array.length: " + items_array.length);
              console.log(items_array);
  
              setItems(items_array);
          }
  
          fetchOrderAndItems();
      }, [userInfo]);
  
      // For each item in the "items" state, return a &lt;tr&gt; element.
      const itemsHtml = items.map(item =&gt; {
          return &lt;tr key={item._id}&gt;
               Something to display.
              &lt;/tr&gt;
      })
  
      // if itemsHtml.length  &gt; 0, render {itemsHtml}, otherwise display "Your cart is empty.".
      // But what is displayed is always "Your cart is empty."
      return &lt;table className="table text-center"&gt;
      &lt;thead style={{border: "none"}}&gt;
      &lt;tr&gt;
          &lt;th style={{border: "none"}} scope="col"&gt;&lt;/th&gt;
          &lt;th style={{border: "none"}} scope="col"&gt;Name&lt;/th&gt;
          &lt;th style={{border: "none"}} scope="col"&gt;Price&lt;/th&gt;
          &lt;th style={{border: "none"}} scope="col"&gt;Qty&lt;/th&gt;
          &lt;th style={{border: "none"}} scope="col"&gt;Subtotal&lt;/th&gt;
          &lt;th style={{border: "none"}} scope="col"&gt;&lt;/th&gt;
      &lt;/tr&gt;
      &lt;/thead&gt;
      {
          itemsHtml.length &gt; 0?
              &lt;tbody&gt;
                  {itemsHtml}
              &lt;/tbody&gt;
              :
              &lt;tbody&gt;
              &lt;tr className="text-center"&gt;
                  &lt;th className="text-center" scope="row" colSpan="6"&gt;Your cart is empty. &lt;/th&gt;
              &lt;/tr&gt;
              &lt;/tbody&gt;
      }
  &lt;/table&gt;
  </code></pre>
  
  <p>The output of the 2 lines of "console.log" is:
  <a href="https://i.stack.imgur.com/eQKnc.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/eQKnc.png" alt="enter image description here"></a></p>
  
  <p>We can see that the length of <code>items_array</code> is 0 while there is content in it, and I think it is because it is asynchronous.</p>
  
  <p>And I guess because the length is 0, so the conditional render of <code>itemsHtml.length &gt; 0?</code> is never true, so the desired content is never rendered.</p>
  
  <p>Could anyone teach me how to solve it?</p>
  
  <p>Thanks</p>