类型错误:即使尚未调用组件,也无法读取未定义的属性“map”

时间:2021-03-06 02:19:29

标签: reactjs react-redux

我目前正在构建的应用中的一个页面是“类别”页面。它呈现来自特定类别的行表。这些行也有注释。

<头>
col x col y 评论
row1 x row1 y 查看
row2 x row1 y 查看

我正在使用 react redux,当我转到“类别”页面时,还没有向状态添加评论,只添加了类别的相关行(他们的评论在我的数据库中的不同表中) . 我正在尝试制作一个组件(“查看”按钮),它将打开一个对话框,在该对话框中获取并显示所选行的注释。

问题是,一旦我进入类别页面,我的标题就会出现错误(错误指向我在下面加星标的地图功能)

class MyComments extends Component {
  state = {
    open: false,
    oldPath: "",
    newPath: "",
  };

  handleOpen = () => {
    let oldPath = window.location.pathname;

    const { categoryId, rowId } = this.props;
    const newPath = `/categories/${categoryId}/row/${rowId}`;

    if (oldPath === newPath) oldPath = `/categories/${categoryId}`;

    window.history.pushState(null, null, newPath);

    this.setState({ open: true, oldPath, newPath });
    this.props.getRow(this.props.rowId);
  };
  handleClose = () => {
    window.history.pushState(null, null, this.state.oldPath);
    this.setState({ open: false });
    this.props.clearErrors();
  };
  render() {
    const {
      row: { comments },
      UI: { loading },
    } = this.props;
    const commentsDialog = loading ? (
      <div>
        <CircularProgress size={200} thickness={2} />
      </div>
    ) : (
      <List>************
        {comments.map((comment) => (
          <ListItem>{comment.body}</ListItem>
        ))}
      </List>***********
    );
    return (
      <Fragment>
        <Button onClick={this.handleOpen}>
          <UnfoldMore color="primary" />
        </Button>
        <Dialog
          open={this.state.open}
          onClose={this.handleClose}
          fullWidth
          maxWidth="sm"
        >
          <Button onClick={this.handleClose}>
            <CloseIcon />
          </Button>
          <DialogContent>{commentsDialog}</DialogContent>
        </Dialog>
      </Fragment>
    );
  }
}

MyComments.propTypes = {
  clearErrors: PropTypes.func.isRequired,
  getRow: PropTypes.func.isRequired,
  rowId: PropTypes.string.isRequired,
  row: PropTypes.object.isRequired,
  UI: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
  row: state.data.row,
  UI: state.UI,
});

const mapActionsToProps = {
  getRow,
  clearErrors,
};

export default connect(mapStateToProps, mapActionsToProps)(MyComments);

您可能会注意到的一件事是我在打开对话框时推送到一个新的 url。我为调试所做的一件事是我注释掉了上面的 comments.map(被 * 包围),然后我可以毫无错误地单击对话框并转到新的 url。一旦在 url 上,我将代码改回 comment.map,它们显示在对话框的列表中。所以我的问题是,我的应用程序试图在将这些选项添加到我的状态之前呈现它们。我想我想知道为什么我的应用程序在对话框打开之前关心这个地图功能?

我的 'getRow' 函数返回一个 json 如下,所以这不是问题,我已经控制台记录了它以确保数据被正确获取,在这和我上面刚刚说的之间,我不认为我的行为或减速器是问题所在,所以我没有添加它们,但如果它们相关,请告诉我。

{
    "categoryId": "id",
    "index": "2",
    "body": "New test",
    "disapproveCount": 0,
    "approveCount": -1,
    "createdAt": "2021-03-05T23:16:26.142Z",
    "rowId": "id",
    "comments": [
        {
            "index": 2,
            "body": "hello",
            "rowId": "id"
        }
    ]
}

我遇到这个问题大约一个星期了,但我先完成了其他所有事情,因为我无法弄清楚,并且还认为在 stackoverflow 上解释起来太难了。我希望这有点道理,仍然不知道我是否正确/完整地解释了它,所以我会非常感激/惊讶地提出任何建议。

另外,理想情况下我只想在对话框中显示这些评论,这样就不需要按下按钮来查看它们,但是在尝试对话框之前我遇到了这个问题,我想加载一个对话框和在一个新的 url 上可以解决这个问题,即,在我打开这个新页面/url 之前不会尝试呈现这些选项

这可能是相关的:

类别页面(称为文档)

class document extends Component {
  componentDidMount() {
    const categoryId = this.props.match.params.categoryId;
    this.props.getCategory(categoryId);
  }

  render() {
    const categoryId = this.props.match.params.categoryId;

    const { category, loading } = this.props.data;
    let placeholder = !loading ? (
      <div>
        <center>
          <h1>{categoryId}</h1>
          <h1> </h1>
        </center>

        <br></br>
        <Paper>
          <TableContainer>
            <TableHead>
              (...)
            </TableHead>
            <TableBody>
              {category.map((row) => (
                <TableRow key={row.rowId}>
                   (...)
                  <TableCell align="left">
                    <MyComments rowId={row.rowId} categoryId={categoryId} />
                  </TableCell>
                       (...)
              </TableRow>
              ))}
            </TableBody>
          </TableContainer>
        </Paper>
        <br></br>
        <MyForm categoryId={categoryId} />
      </div>
    ) : (
      <p>Loading...</p>
    );
    return <div>{placeholder}</div>;
  }
}

document.propTypes = {
  getCategory: PropTypes.func.isRequired,
  data: PropTypes.object.isRequired,
};

const mapStateToProps = (state) => ({
  data: state.data,
});

export default connect(mapStateToProps, { getCategory })(document);

我不确定这是否是确切的问题,但我认为 Tl;Dr 是:为什么我的对话框中的 map 函数在尚未调用时关心未定义的东西? 非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

放置一个?对象键后的符号。在继续操作之前,它将检查对象键的值是否为 undefined 或 null。


Math.random()