【问题标题】:React Array.map does not recognise JSON data as arrayReact Array.map 无法将 JSON 数据识别为数组
【发布时间】:2018-08-28 18:36:17
【问题描述】:

这可能是一个非常简单的修复,但我无法弄清楚为什么 map 函数无法将输入识别为数组。

我有一个 Dilemma 模型,其中包含一组用户 cmets。我获取数据并将其映射到我的反应组件的状态。然后我尝试将数据作为道具解析到我尝试映射数据的子组件。

困境减少器

const initialState = {
  loading: false,
  dilemma: {}
};

export default function(state = initialState, action) {
  switch (action.type) {
    case GET_DILEMMA:
      return {
        ...state,
        dilemma: action.payload,
        loading: false
      };
    case GET_DILEMMAS:
      return {
        ...state,
        dilemmas: action.payload,
        loading: false
      };
    case CREATE_DILEMMA:
      return {
        ...state,
        dilemmas: [action.payload, ...state.dilemmas]
      };
    case DELETE_DILEMMA:
      return {
        ...state,
        dilemmas: state.dilemmas.filter(
          dilemma => dilemma._id !== action.payload
        )
      };
    case DILEMMAS_LOADING:
      return {
        ...state,
        loading: true
      };
    default:
      return state;
  }
}

有状态组件中的this.props

{
  "match": { "path": "/", "url": "/", "isExact": true, "params": {} },
  "location": { "pathname": "/", "search": "", "hash": "", "key": "crpcmj" },
  "history": {
    "length": 50,
    "action": "POP",
    "location": { "pathname": "/", "search": "", "hash": "", "key": "crpcmj" }
  },
  "dilemmas": {
    "loading": false,
    "dilemma": {
      "red_votes": 0,
      "blue_votes": 0,
      "_id": "5b855fcbdfa436e0d25765fa",
      "user": "5b855f9fdfa436e0d25765f9",
      "prefix": "Hvis du skulle vælge",
      "title": "Svede remoulade",
      "red": "Gå med rustning resten af dit liv",
      "blue": "Svede remoulade resten af dit liv",
      "likes": [],
      "comments": [
        {
          "date": "2018-08-28T17:28:23.340Z",
          "_id": "5b858637b6f6a6e6218eeaba",
          "user": "5b855f9fdfa436e0d25765f9",
          "text": "This is a test3 comment",
          "author": "Albyzai"
        },
        {
          "date": "2018-08-28T17:28:19.915Z",
          "_id": "5b858633b6f6a6e6218eeab9",
          "user": "5b855f9fdfa436e0d25765f9",
          "text": "This is a test2 comment",
          "author": "Albyzai"
        },
        {
          "date": "2018-08-28T15:50:18.792Z",
          "_id": "5b856f3aed156de48a270766",
          "user": "5b855f9fdfa436e0d25765f9",
          "text": "This is a test comment",
          "author": "Albyzai"
        }
      ],
      "date": "2018-08-28T14:44:27.413Z",
      "slug": "svede-remoulade",
      "__v": 3
    }
  },
  "errors": {}
}

有状态组件

import React, { Component } from "react";
import propTypes from "prop-types";
import { connect } from "react-redux";
import { getDilemma, addLike, removeLike } from "../../actions/dilemmaActions";

import Dilemma from "./../dilemma/Dilemma";
import Divider from "./../dilemma/Divider";
import CommentFeed from "../dilemma/CommentFeed";

class DilemmaLayout extends Component {
  constructor() {
    super();
    this.state = {
      title: "",
      prefix: "",
      red: "",
      blue: "",
      red_votes: 0,
      blue_votes: 0,
      likes: [],
      comments: [],
      errors: {}
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.errors) {
      this.setState({ errors: nextProps.errors });
    }

    if (nextProps.dilemmas.dilemma) {
      const dilemma = nextProps.dilemmas.dilemma;

      this.setState({
        id: dilemma._id,
        user: dilemma.user,
        title: dilemma.title,
        prefix: dilemma.prefix,
        red: dilemma.red,
        blue: dilemma.blue,
        red_votes: dilemma.red_votes,
        blue_votes: dilemma.blue_votes,
        likes: [dilemma.likes],
        comments: [dilemma.comments]
      });
    }
  }

  render() {
    return (
      <div>        
        <CommentFeed comments={this.state.comments} />
      </div>
    );
  }
}

DilemmaLayout.propTypes = {
  getDilemma: propTypes.func.isRequired,
  addLike: propTypes.func.isRequired,
  removeLike: propTypes.func.isRequired,
  dilemmas: propTypes.object.isRequired
};

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

export default connect(
  mapStateToProps,
  { getDilemma, addLike, removeLike }
)(DilemmaLayout);

功能组件接收道具

import React from "react";
import Comment from "./Comment";
import { Container } from "reactstrap";

const CommentFeed = comments => {
  const commentArray = comments.map(comment => {
    <Comment author={comment.author} text={comment.text} />;
  });

  return <Container>{commentArray}</Container>;
};

export default CommentFeed;

【问题讨论】:

  • 在您的 CommentFeed 函数中,console.log 记录 cmets 以查看它是什么...
  • 它返回{"comments":[]},所以它必须是我将它解析为导致问题的子组件的方式。
  • 是的(来自下面的回答 cmets)请发布您的减速器等 - cmets/困境有问题...
  • 我已经使用有状态组件中 this.props 中的 JSON 数据以及 reducer 更新了帖子。
  • StackBlitz 示例有帮助吗?我认为这真的归结为一些基本的条件渲染。

标签: arrays json reactjs react-redux


【解决方案1】:

尝试使用类似 ES6 destructuring assignment 的东西从 props 上的 CommentFeed 组件中提取/解压缩 prop comments。之所以需要这样做,是因为comments 数组直接传递给组件,而是将props 对象传递给包含comments 属性的组件。

const CommentFeed = ({ comments }) => {
  const commentArray = comments.map(comment =>
    <Comment author={comment.author} text={comment.text} />;
  );

  return <Container>{commentArray}</Container>;
};

或访问commentsprops.comments

const CommentFeed = props => {
  const commentArray = props.comments.map(comment =>
    <Comment author={comment.author} text={comment.text} />;
  );

  /* also an option
    const { comments } = props;
    const commentArray = comments.map(comment => {
      <Comment author={comment.author} text={comment.text} />;
    });
  */

  return <Container>{commentArray}</Container>;
};

此外,无法从所提供的内容中分辨出来,但以下状态设置可能会导致问题,原因如下:

componentWillReceiveProps(nextProps) {
  if (nextProps.errors) {
    this.setState({ errors: nextProps.errors });
  }

  if (nextProps.dilemmas.dilemma) {
    const dilemma = nextProps.dilemmas.dilemma;

    this.setState({
      // ...
      likes: [dilemma.likes],
      comments: [dilemma.comments]
    });
  }
}
  1. 如果dilemma.likes 是一个数组。你要么只需要likes: dilemma.likeslikes: [...dilemma.likes]
  2. 如果dilemma.comments 是一个数组。你要么只需要comments: dilemma.commentscomments: [...dilemma.comments]

在创建嵌套数组(例如 [[]])时可能会出现问题,这会导致您在 CommentFeed 组件中的 comments.map() 中描述的错误,因为 map() 将尝试访问属性 author嵌套数组项,例如 [{ "author":"Albyzai" }].author

鉴于componentWillReceiveProps 将在未来被弃用,为什么不直接使用comments 和来自商店的其他属性传递给子组件或渲染?您在 cmets 中提到,各种道具在初始渲染时是未定义/空的。您可能需要结合使用商店状态中的 loading 属性和某种条件渲染。

render() {
  const { dilemmas, errors } = this.props;

  if (errors) {
    return <div>{errors}</div>;
  } else if (!dilemmas.dilemma || dilemmas.loading) {
    return <div>Loading...</div>;
  } else {
    return <CommentFeed comments={dilemmas.dilemma.comments} />;
  }
}

我创建了一个StackBlitz,在基本层面展示了这个功能。

希望对您有所帮助!

【讨论】:

  • 不幸的是,两种解决方案都返回“无法读取未定义的属性作者”。
  • 你确定comments 来自第一个示例或props.comments 在呈现CommentsFeed 时具有值吗?如果有,是一个数组吗? const dilemma = nextProps.dilemmas.dilemma; 也可能有问题,nextProps.dilemmas 是一个数组吗?如果是这样,您将无法使用 . 表示法访问数组中的条目。
  • 这个答案解决了从传递给功能组件的props访问comments的问题。您可能需要创建一个单独的问题来解决组件 Comment 如何处理 comments 数组。
  • 您可能需要在您的问题中分享您的 dilemmas 道具结构。目前尚不清楚它的结构以及setState() 实际设置的内容,包括nextProps.dilemmas.dilemma 实际返回的内容。
  • 我设法截取了父组件中的状态截图:imgur.com/a/DBHg6Ft
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多