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

React组件渲染时出现Uncaught TypeError: map不是函数问题求助

解决Uncaught TypeError: ...map is not a function报错

核心报错原因

你在父组件中通过comments.map循环,给每个<CommentsBlock>传递的items是单个评论对象,但在CommentsBlock组件内部,你把items当成数组来执行map方法——非数组对象没有map方法,这直接触发了报错。

另外还有一个潜在隐患:从Redux获取的comments初始值可能不是数组(比如undefined/null),这也会导致父组件的comments.map触发相同类型的报错。

修复方案

方案1:调整CommentsBlock,适配单个评论对象

既然父组件是逐个传递评论对象,CommentsBlock不需要再做循环,直接渲染单条评论即可:

export const CommentsBlock = ({
  id,
  items,
  children,
  isLoading = true,
  isEditable = false,
}) => {
  const dispatch = useDispatch();
  const onClickRemove = () => {
    if (window.confirm("Вы действительно хотите удалить статью?")) {
      //dispatch(fetchRemovePosts(id));
    }
  };

  // 加载状态渲染单个骨架屏
  const renderLoading = () => (
    <React.Fragment>
      <ListItem alignItems="flex-start">
        <ListItemAvatar>
          <Skeleton variant="circular" width={40} height={40} />
        </ListItemAvatar>
        <div style={{ display: "flex", flexDirection: "column" }}>
          <Skeleton variant="text" height={25} width={120} />
          <Skeleton variant="text" height={18} width={230} />
        </div>
      </ListItem>
      <Divider variant="inset" component="li" />
    </React.Fragment>
  );

  // 渲染单条评论
  const renderComment = () => (
    <React.Fragment>
      <ListItem alignItems="flex-start">
        <ListItemAvatar>
          <Avatar alt={items.user.fullName} src={items.user.avatarUrl} />
        </ListItemAvatar>
        <ListItemText
          primary={
            <Typography
              style={{
                display: "flex",
                justifyContent: "space-between",
              }}
            >
              {items.user.fullName}
              {isEditable ? (
                <IconButton color="secondary" style={{ padding: 0 }}>
                  <DeleteIcon />
                </IconButton>
              ) : (
                ""
              )}
            </Typography>
          }
          secondary={items.text}
        />
      </ListItem>
      <Divider variant="inset" component="li" />
    </React.Fragment>
  );

  return (
    <SideBlock title="Комментарии">
      <List>
        {isLoading ? renderLoading() : renderComment()}
      </List>
      {children}
    </SideBlock>
  );
};

方案2:父组件直接传递整个评论数组给CommentsBlock

如果想让CommentsBlock负责循环所有评论,父组件不需要单独做map,直接把整个数组传过去:

// 父组件代码
<CommentsBlock
  items={comments}
  isLoading={!comments}
>
  <Index />
</CommentsBlock>

同时给CommentsBlock的items设置默认空数组,避免非数组值导致报错:

export const CommentsBlock = ({
  id,
  items = [], // 兜底空数组
  children,
  isLoading = true,
  isEditable = false,
}) => {
  // 原循环逻辑保留,此时items是数组可正常map
  // ...其余代码不变
};

修复父组件comments的初始值问题

从Redux获取comments时,给它兜底一个空数组,避免初始值为非数组类型:

const comments = useSelector((state) => state.comment.data || []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 15:05:27