You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React新手求助:TypeError: Cannot read property 'map' of undefined——嵌套数组遍历报错问题

Hey there! Let's break down why you're hitting that TypeError and fix it step by step.

First, let's look at the two main issues in your code:

1. Async setState Order Causes Intermediate Render with Empty State

In your useEffect callback, you're calling setIsLoaded(true) before updating your works state with setItems(result). Since React state updates are asynchronous, this triggers a render where isLoaded is true but works is still its initial value ([], an empty array). When you try to access works.tags on an empty array, you get undefined—and calling map() on undefined throws that error you're seeing.

2. Mismatch Between API Response Structure and Your State

Looking at your API response, it returns an object with a works array (containing a single work object). But you're setting your entire result object to the works state, so works becomes { works: [ {...} ] } instead of the single work object. That means works.tags doesn't exist—your tags are actually at works.works[0].tags.


Fixing the Issue

Let's adjust your code to fix both problems:

Step 1: Fix the State Update Order and API Data Extraction

Update your useEffect to first extract the correct work object from the API response, update the state, then mark it as loaded. Also, don't forget to add id to the dependency array (your effect should re-run when the id param changes):

useEffect(() => {
  let cleanupFunction = false;
  fetch(`http://localhost:3001/works/${id}`)
    .then(res => res.json())
    .then(
      (result) => {
        console.log(result);
        // Extract the first work from the works array in the response
        if(!cleanupFunction) setItems(result.works[0]);
        setIsLoaded(true); // Move this after setting items
      },
      (error) => {
        setIsLoaded(true);
        setError(error);
      }
    )
  return () => cleanupFunction = true;
}, [id])

Step 2: Adjust Initial State and Add Safeguards

Change your initial works state to null instead of an empty array, so we can explicitly check if the data is ready. Then, in your render section, add a check for works, wrap list items in a proper <ul> container, and add a key prop to each <li> (React requires this for list optimization):

const [works, setItems] = useState(null);

// ...

else {
  if (!works) {
    return <div className="works no-data">No work found</div>;
  }
  return (
    <>
      <Header />
      <div className="works item">
        <ul>
          {works.tags?.map(item => (
            <li key={item}>{item}</li>
          ))}
        </ul>
      </div>
      <Footer />
    </>
  );
}

The ?. optional chain operator ensures that if works.tags is ever undefined (for example, if the API response doesn't include tags), it won't throw an error—it'll just skip rendering the list.


Why Did Direct Access Seem to Work?

When you tested {works.tags} or {works.tags[0]}, you might have been looking at the state after it had updated successfully, but the error happens in that intermediate render where works is still the initial empty array. React's state updates are batched, so that in-between render can be easy to miss!

内容的提问来源于stack exchange,提问作者MKTF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 15:13:10