类型错误:无法读取未定义的属性(读取“length”)

3

我正在开发我的第一个全栈 MERN 应用程序,它允许用户将多个地点添加到数组中。尝试使用 .length 映射数组以显示用户的地点数量。代码在不使用 .length 时可以正常工作,但一旦使用它就会崩溃。

import React from 'react';

import UserItem from './UserItem';
import Card from '../../shared/components/UIElements/Card/Card';
import './UsersList.css';


const UsersList = props => {
    if (props.items.length === 0) {
        return (
            <div className="center">
                <Card>
                    <h2>No users found.</h2>
                </Card>
            </div>
        );
    }


    return (
        <ul className="users-list">
            {props.items.map(user => (
                <UserItem
                    key={user.id}
                    id={user.id}
                    image={user.image}
                    name={user.name}
                    // placeCount={user.places.length}
                    placeCount={user.places}
                />
            ))}
        </ul>
    );


};

export default UsersList;

完整的错误堆栈:

Uncaught TypeError: Cannot read properties of undefined (reading 'length')

The above error occurred in the <UsersList> component:

  
Consider adding an error boundary to your tree to customize error handling behavior.

Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
  

我在后端和前端文件中进行了.length的关键字搜索,以确保代码没有任何拼写错误,但是我无法弄清楚为什么添加.length不起作用。

我已经阅读了几篇不同的帖子,但是找不到可行的解决方案。

如有任何见解,将不胜感激。目前我只是注释掉了.length,以便继续工作。谢谢!


1
你如何使用这个组件? - Daniel A. White
2
看起来 items 未定义,你尝试过记录它吗?你必须将 items 作为 props 传递给 UsersList<UsersList items={someArrayOfItems} /> - JEEngineer
谢谢您的快速回复 - 我刚试了一下,但出于某种原因我仍然遇到了相同的错误。但 Sameer 的回复对我有用。再次感谢! - SJo
4个回答

2
您可以定义一个默认值来修复items
const UsersList = ({ items = [] }) => {
  if (items.length === 0) {
    return (
      ...
    );
  }

  return (
    <ul className="users-list">
      {items.map((user) => (
        ...
      ))}
    </ul>
  );
};

谢谢您的快速回复!我刚试了一下,但出于某种原因仍然遇到相同的错误。 - SJo

2
其他答案都集中在prop.items列表上,但是在你的问题中提到,当尝试访问user中的places的长度时,会出现异常。
你会收到错误消息,因为某些用户可能没有列出任何地点,因此没有地点列表->没有长度属性。
要解决这个问题,您需要检查地点列表是否存在,然后访问其长度:
placeCount={ user.places ? user.places.length : 0 }

这里,我们使用三元操作符来检查user.places是否存在,如果存在则使用其长度,否则使用零。 编辑: 如Phil在下面的评论中指出的那样,您还可以使用合并运算符,它更清晰简洁,像这样:
placeCount={ user.places?.length ?? 0 }

这个语法简单地表示,如果用户的places属性有一个长度值,则使用该值,否则将零作为默认值。


1
可以使用 user.places?.length ?? 0 - Phil
谢谢你们两个!我刚刚都试了一下,它们都可以用!我已经被卡住好几个小时了,一直在回溯和找出我的错误。你们俩解决了我很多的压力!我感激你们花时间提供一个可行的解决方案,并在过程中解释——我是一个新手,正在努力学习,我感激像你们这样真正尝试帮助的善良人士。非常感谢你们!! - SJo

2

将这个if条件从这个改为:

if (props.items.length === 0) {

if (!props.items?.length) {

应该可以工作。

同样,如果用于地点,您可以使用三元运算符检查长度是否存在于地点数组中。

为什么?因为来自API的项目可能是nullundefined,所以数组上的length属性可能会丢失。

此外,使用非运算符将使此条件在项目长度为0或为null或undefined或任何falsy值时成立。


谢谢回复-我刚尝试了一下,但由于某些原因仍然遇到相同的错误。 - SJo

1

在这里,你可以使用对象解构赋值。如果你不确定数据是否存在。

JSX 总是先渲染,然后才是 props,在某些情况下它可能会渲染空的 JSX。

你可以像这样在组件中进行更改。

const UsersList = props => {
const { items = [] } = props

    // checking whether its an array or not and have some items in it
    if (!Array.isArray(items) || items.length === 0) {
        return (
            <div className="center">
                <Card>
                    <h2>No users found.</h2>
                </Card>
            </div>
        );
    }


    return (
        <ul className="users-list">
            {items.map(user => {
              const { id = "", image = "", name = "", places = "" } = user
              return <UserItem
                key={id}
                id={id}
                image={image}
                name={name}
                // placeCount={user.places.length}
                placeCount={places}
              />
           })}
        </ul>
    );
};

你真是个天才!!!!!!这个解决方案起作用了!哦我的天啊,谢谢你!!!!!!我感觉自己已经尝试了所有的方法-我整整一天都在查找文件,但是找不到解决方法。我看了很多Stack文章,但是什么都没用。非常感谢你!! - SJo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接