Захват и отображение одного объекта JSON в React-Redux - PullRequest
0 голосов
/ 14 июля 2020

Я сделал учебное пособие и могу отобразить все мои объекты «Статьи», но я не могу понять, как изменить код, чтобы получить один конкретный объект c и сохранить его в состоянии. Я пробовал много разных вещей, но продолжаю получать «TypeError: Cannot read property 'name' of undefined».

Одно примечание, идентификатор, который я ищу, хранится в 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;
  }
}

маршруты /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;

модели / Артикул. 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);

магазин. 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;

1 Ответ

0 голосов
/ 14 июля 2020

Во-первых, если возможно, я предлагаю вам пересмотреть, как вы храните свои данные в узле статей. В массиве статей это избавит вас от множества сложностей, если вы сохраните статьи как объект, а не массив с идентификатором статьи в качестве ключа, если мы обновляем / удаляем / получаем доступ к этим статьям. Во-вторых, статья должна быть дочерним компонентом статей, который будет гарантировать конкретную статью. всегда будет существовать, когда компонент статьи загружается

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

В этом сценарии ваш блок переключения будет выглядеть так:

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,
      };

Я не тестировал код. Но это должно дать вам представление, как go об этом

...