【问题标题】:TypeError: Cannot read property 'map' of undefined when I try to use items.mapTypeError:当我尝试使用 items.map 时,无法读取未定义的属性“地图”
【发布时间】:2021-09-01 12:22:56
【问题描述】:

我正在尝试使用来自 db 的数据来渲染卡片。当我运行代码时,我收到错误“无法读取未定义的属性“映射””。有任何想法吗?我做错了什么

const ProductList =  () =>
 {
  const [prodList, setProdList] = useState();
  const [ pass, setPass] = useState();
    const getitems = async () => {await axios.get('http://localhost:3001/services').then((response) => setPass(response.data));}

  useEffect(() => {
    getitems().then((pass) => setProdList(pass));
  }, []);
  return (
    <>
   
      <Container maxWidth={false}>
        <ProductListToolbar />
        <Box sx={{ pt: 3 }}>
          <Grid
            container
            spacing={3}
          >
            {prodList.map((product) => (
              <Grid
                item
                key={product.serviceID}
                lg={4}
                md={6}
                xs={12}
              >
                <ProductCard product={product} />
              </Grid>
            ))}
          </Grid>
        </Box>
      </Container>
    </>)}

export default ProductList;

【问题讨论】:

  • 将初始值作为[] 传递给您的状态。 const [prodList, setProdList] = useState([]);
  • 这里还有 Productcard 组件:codesandbox.io/s/objective-rgb-occ48?file=/src/App.js
  • @Shyam 我得到了同样的错误。另外它说“(匿名函数)> 21 | getitems().then((pass) => setProdList(pass));”
  • 已添加我的答案!请看一看。

标签: reactjs


【解决方案1】:

我们需要对您的代码进行一些更改,

  1. 始终将初始值传递给 state ,否则它将是未定义的。
  2. 我们不需要状态pass,我们没有在代码中的任何地方使用它。
  3. 我们不应将 async/await 与 then/catch 混合使用。我们应该使用它们中的任何一个,而不是两者。
  4. 在进行 API 调用时,最好有加载状态,这样我们就可以向用户显示一些有意义的消息,直到我们获取数据。

通过上述更改,我们可以将您的代码重构为

const ProductList = () => {
  const [prodList, setProdList] = useState([]);
  const [loading, setLoading] = useState(false);

  const getItems = async () => {
    setLoading(true);
    try {
      const response = await axios.get('http://localhost:3001/services');

      setProdList(response.data);
    } catch (error) {
      console.log(error);
    } finally {
      setLoading(false);
    }
  };

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

  if (loading) {
    return <p> Fetching the Products ... </p>;
  }

  return (
    <>
      <Container maxWidth={false}>
        <ProductListToolbar />
        <Box sx={{pt: 3}}>
          <Grid container spacing={3}>
            {prodList.map((product) => (
              <Grid item key={product.serviceID} lg={4} md={6} xs={12}>
                <ProductCard product={product} />
              </Grid>
            ))}
          </Grid>
        </Box>
      </Container>
    </>
  );
};

export default ProductList;

【讨论】:

    【解决方案2】:

    @Shyam 已经向您的代码库提出了非常好的建议。我将尝试解释为什么您以前的方法不起作用。

    这很可能是因为你的 getitems 函数(一个小提示:我试图在命名事物时保持大小写一致,所以我建议你将函数名称更改为 getItems)。简而言之,您的 getItems 函数不会返回带有 data 的承诺。

    JS Promise 就像一个链条。如果前面的“节点”返回一些东西,后面的“节点”将接收该数据作为参数

    然而,getItems 的承诺链中的最后一个动作是.then(response =&gt; setPass(response.data);但是setPass 函数returns undefined --> getItems 返回Promise&lt;undefined&gt;

    因此:当您使用getItems.then(pass =&gt; setProdList(pass)) 时(在您的useEffect 中)

    --> Promise&lt;undefined&gt;.then(pass =&gt; setProdlist(pass))

    --> pass 收到 undefined 值

    --> setProdList(undefined)

    --> 无法读取map 的undefined

    我希望以上这些步骤有助于说明数据是如何在承诺链中传递的。 JS Promise 不是某种魔法——你需要小心你在你的 Promise 链中返回的内容。

    问题的解决方案是对您的代码进行一些重构。您有一些不太好的设计决策:

    • useState 中没有初始状态
    • 您正在将 async/await 与 then 混合使用
    • 您在getItems 函数内部(使用setPass)和外部(使用setProdList)调用setState。这与 IMO 有点不一致,并且使调试变得更加困难。要么都在里面,要么都在外面。

    因此,我建议将.then 调用简单地放在getItems 函数之外。让getItems 承担进行 Axios 调用的单一职责,无论我们想对响应做什么,我们都将它放在useEffect 中。并为您的useState 使用一些初始状态

    const [prodList, setProdList] = useState([]);
    const [pass, setPass] = useState([]);
    const getItems = async () => {
      await axios.get("http://localhost:3001/services");
    };
    
    useEffect(() => {
      getItems().then((response) => {
        const pass = response.data;
        // Use both `setState` here, no need to separate them
        setPass(pass);
        setProdList(pass);
      });
    }, []);
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 2019-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-05
      相关资源
      最近更新 更多