【问题标题】:Grab and display single JSON object in React-Redux在 React-Redux 中抓取并显示单个 JSON 对象
【发布时间】:2020-11-03 19:58:59
【问题描述】:

我做了一个教程,能够显示我所有的文章对象,但我不知道如何修改代码以获取一个特定对象并将其存储在状态中。我尝试了很多不同的方法,但我不断收到“TypeError: Cannot read property 'name' of undefined”。

请注意,我要查找的 id 存储在“this.props.match.params.id”中,但我真的不知道这意味着什么或如何使用它。谢谢

ArticleShow.js

import React, { Component } from "react";
import { Container } from "reactstrap";
import { connect } from "react-redux";
import { getArticle } from "../actions/articleActions";
import PropTypes from "prop-types";

class articleShow extends Component {
  componentDidMount() {
    this.props.getArticle();
  }

  render() {
    const { article } = this.props.article;


    return (
      <Container>
        {article.name}
        <br />
        {article.author}
        <br />
        {article.body.split("\r").map((c) => {
          return <p> {c} </p>;
        })}
        <br />
      </Container>
    );
  }
}

ArticleShow.propTypes = {
  getArticle: PropTypes.func.isRequired,
  article: PropTypes.object.isRequired,
};

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

export default connect(mapStateToProps, { getArticle })(ArticleShow);

articleActions.js

import axios from "axios";

import {
  GET_ARTICLES,
  GET_ARTICLE,
} from "./types";

export const getArticles = () => (dispatch) => {
  dispatch(setArticlesLoading());
  axios.get("/api/articles").then((res) =>
    dispatch({
      type: GET_ARTICLES,
      payload: res.data,
    })
  );
};

export const getArticle = (id) => (dispatch) => {
  dispatch(setArticlesLoading());
  axios.get(`/api/articles/${id}`).then((res) =>
    dispatch({
      type: GET_ARTICLE,
      payload: res.data,
    })
  );
};

articleReducer.js

import {
  GET_ARTICLES,
  GET_ARTICLE,
} from "../actions/types";

const intialState = {
  articles: [],
  loading: false,
};

export default function (state = intialState, action) {
  switch (action.type) {
    case GET_ARTICLES:
      return {
        ...state,
        articles: action.payload,
        loading: false,
      };
    case GET_ARTICLE:
      return {
        ...state,
        article: action.payload,
        loading: false,
      };
  default:
      return state;
  }
}

routes/api/articles.js

const express = require("express");
const router = express.Router();

// Article Model
const Article = require("../../models/Article");

router.get("/", (req, res) => {
  Article.find()
    .sort({ date: -1 })
    .then((articles) => res.json(articles));
});

router.get("/:id", (req, res) => {
  Article.findById(req.params.id).then((article) => res.json(article));
});

module.exports = router;

models/Article.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

// create schema
const ArticleSchema = new Schema({
  name: {
    type: String,
    required: true,
  },
  author: {
    type: String,
    required: true,
  },
  body: {
    type: String,
    required: true,
  },
  date: {
    type: Date,
    default: Date.now,
  },
});

module.exports = Article = mongoose.model("article", ArticleSchema);

store.js

import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers";

const initialState = {};

const middleware = [thunk];

const store = createStore(
  rootReducer,
  initialState,
  compose(
    applyMiddleware(...middleware),
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  )
);

export default store;

【问题讨论】:

  • 您会用文章数据更新文章节点吗?另外,在文章数组中,您能否分享一下您正在分享的代表性数据
  • 这是所有 Articles 对象的 JSON,我试图通过其 ID 获取其中一个。 ``` {"_id":"5f0b628f172467147fbed0c2","name":"Article 4","author":"Carol Henderson","body":"orem Ipsum 就是 d,{"_id":"5f0b6208b4841b13d8f08363", "name":"Article 3","author":"Joe Smith","body":"orem Ipsum is"}] ``

标签: javascript reactjs redux react-redux


【解决方案1】:

首先,如果可能的话,我建议您重新考虑如何在文章节点中存储数据。在文章数组中,如果您将文章存储为对象而不是数组,如果我们正在更新/删除/访问这些文章,那么它将为您节省很多复杂性 其次,文章应该是文章的子组件,这将确保在文章组件加载时始终存在特定文章

articles: {
  5f0b628f172467147fbed0c2: {
    "name":"Article 4",
    "author":"Carol Henderson"
  }
}

在这种情况下,您的 switch 块将如下所示:

case GET_ARTICLES:
      return {
        ...state,
        articles: action.payload.reduce((accObj, curObj) => {...accObj, [curObj._id]: curObj}, {}),
        loading: false,
      };
case GET_ARTICLE:
      return {
        ...state,
        articles: {
          [action.payload._id]: action.payload,
        },
        loading: false,
      };

但是,如果由于某些用例而将其保持在当前形状,则可以尝试以下操作:

case GET_ARTICLE:
      // find the article and merge more details
      const article = state.articles.find((art) => art._id === action.payload._id);
      article = {...article, ...action.payload};
      // since state has reference of article via references, your state has now new values.
      return {
        ...state,
        loading: false,
      };

我还没有测试过代码。但它应该让你知道如何去做

【讨论】:

  • 表示“文章”没有定义。这是因为在 ArticleShow.js 中,我有 componentDidMount() { this.props.getArticle();并且不包含 ID 作为参数?我该怎么做?
  • 我的错。文章没有定义。所以你必须以state.articles 的身份访问它
  • 我得到了和以前一样的错误,'TypeError: Cannot read property 'name' of undefined' 由于文章数组为空。
  • 在您发送 getArticle 操作时,我们是否已经填充了文章。如果您可以共享代码,那将有助于我查明。
  • 不,抱歉我没有具体说明。数据来自 MongoDB,文章的初始状态是一个空数组。我现在会放更多的代码。感谢您的宝贵时间
猜你喜欢
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 2017-11-03
  • 2017-02-09
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
相关资源
最近更新 更多