【问题标题】:Unable to Render/Return a MongoDB Record by ID in React无法在 React 中按 ID 呈现/返回 MongoDB 记录
【发布时间】:2019-07-04 13:39:08
【问题描述】:

经过多次尝试和轻微崩溃后,我仍然无法在我的 React 前端通过其 ID 成功返回对象。即使根据 Redux Dev Console 和多个 console.logs 显示数据可用,我在我的 Post 组件中仍然收到相同的错误“无法读取属性 'XXX'”。我已经提供了完整的 Post 组件以及下面的所有其他相关代码,但这就是我的意思....

renderPost() {
    console.log(this.props.post);
      //  {  _id: '5d1d93348a966c08c1f4bedb',
      //     title: 'Testing getPost',
      //     user: '5d1129e503da62058a95c481', }

    console.log(this.props.post.title);
      //  ERROR Cannot read property 'title' of undefined

    return (
      <div className="content">
        <h4 className="title">POST.TITLE HERE</h4>
      </div>
    );}

为什么我可以访问并返回 this.props.post 但不能访问和返回 this.props.post.title 之类的内容?通过 PostMan 测试在后端一切正常,所以我肯定在前端搞砸了一些东西,这意味着 getPost 操作创建者、GET_POST reducer 或 Post 组件。

老实说,我认为它在减速器或 Post 组件中的某个地方,但我正在旋转我的轮子,同时我的头撞在墙上,因此非常感谢任何和所有帮助。

如果我提供的内容不清楚或缺少,我深表歉意。我对编程很陌生,这是我第一次在这里发帖,所以请原谅任何不可避免的礼仪灾难。

getPost Action Creator

export const getPost = _id => async dispatch => {
  const res = await axios.get(`/api/posts/${_id}`);
  dispatch({ type: GET_POST, payload: res.data });
};

getPost 操作负载

{  type: 'GET_POST',
   payload: {
     _id: '5d1d93348a966c08c1f4bedb',
     title: 'Testing getPost',
     user: '5d1129e503da62058a95c481', }}

GET_POST 减速器

import { GET_POSTS, GET_POST } from '../actions/types';
import _ from 'lodash';

export default (state = {}, action) => {
  switch (action.type) {
    case GET_POSTS:
      return { ...state, ..._.mapKeys(action.payload, '_id') };
    case GET_POST:
      return { ...state.post, [action.payload._id]: action.payload };
    default:
      return state; }

结果帖子状态

  {  posts: {
       '5d1d93348a966c08c1f4bedb': {
         _id: '5d1d93348a966c08c1f4bedb',
         title: 'Testing getPost',
         user: '5d1129e503da62058a95c481',
  }}}

发布组件

import React from 'react';
import { connect } from 'react-redux';
import { getPost } from '../actions';

class Post extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      post: {}
    };}

  componentDidMount() {
    this.props.getPost(this.props.match.params.id);
      // using params._ID instead  results in CastError: 
      // Cast to ObjectId failed for value "{ _id: 'undefined' }" 
      // at path "_id" for model "Posts" }

  renderPost() {
    return (
      <div className="content">
        <h4 className="title">WANT TO RETURN POST.TITLE HERE</h4>
      </div>
    );}

  render() {
    return (
      <div className="content-top">
        <div>{this.renderPost()}</div>
      </div>
    );}}

const mapStateToProps = (state, ownProps) => {
  return { post: state.posts[ownProps.match.params.id] };
    // ._id at the end results in post being undefined
};

export default connect(
  mapStateToProps,
  { getPost })(Post);

附加代码

MongoDB 架构

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

const postSchema = new Schema({
  title: { type: String, required: true },
  user: { type: Schema.Types.ObjectId, ref: 'Users' }
  });

const Post = mongoose.model('Posts', postSchema);
module.exports = Post;

MongoDB 按 ID 路由查找

const mongoose = require('mongoose');
const Post = mongoose.model('Posts');

  app.get('/api/posts/:id', async (req, res) => {
    const post = await Post.findById({ _id: req.params.id });
    res.json(post);
  });

REDUX 减速器

export default (state = {}, action) => {
  switch (action.type) {

    case GET_POSTS:
      return { ...state, ..._.mapKeys(action.payload, '_id') };

        //  mapKeys is a function in Lodash that takes an array              
        //  and returns an object. Whatever the value of ‘_id’                
        //  is for an object inside an array is now the key for 
        //  that object in a new state object.

    case GET_POST:
      return { ...state.post, [action.payload._id]: action.payload };

        //  Changing to action.payload.ID results in an undefined 
        //  record being created in posts.
        //   { posts: {
        //       undefined: {
        //         _id: '5d1de8e47691dc12cc64b05c',
        //         title: 'xxxxxxxxx',       
        //         user: '5d1129e503da62058a95c481' }}}

    default:
      return state;
  }};

后列表组件

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { getPosts } from '../actions';

class PostsList extends Component {

  componentDidMount() {
    this.props.getPosts(); }

  renderPosts() {
    return this.props.posts.map(post => {
      return (
        <div className="content" key={post._id}>
          <h4 className="title">
            <Link className="title" to={`/posts/${post._id}`}>
              {post.title}
            </Link>
          </h4>
        </div>
      );});}

  render() {
    return (
      <div className="content-top">
        <div>{this.renderPosts()}</div>
      </div>
    );}}

const mapStateToProps = state => {
  return {
    posts: Object.values(state.posts)
  };};

export default connect(
  mapStateToProps,
  { getPosts }
)(PostsList);

【问题讨论】:

  • 很奇怪。在控制台之前的一行记录整个对象,在下一行它是未定义的。试着安慰这个const {title} = this.props.post; console.log(title)
  • 不幸的是,它导致了另一个未定义的属性值。

标签: reactjs mongodb redux


【解决方案1】:

getPost 操作是异步的

你能像下面这样更新 Post 组件并试一试吗?

import React from 'react';
import { connect } from 'react-redux';
import { getPost } from '../actions';

class Post extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loaded: false,
      post: {}
    };}

  async componentDidMount() {
    await this.props.getPost(this.props.match.params.id);
    await this.setState({loaded: true}); 
  }

  renderPost() {
    return (
      <div className="content">
        <h4 className="title">{this.props.post.title}</h4>
      </div>
    );}

  render() {
    return (
      <div className="content-top">
        <div>{this.state.loaded && this.renderPost()}</div>
      </div>
    );}}

const mapStateToProps = (state, ownProps) => {
  return { post: state.posts[ownProps.match.params.id] };
    // ._id at the end results in post being undefined
};

export default connect(
  mapStateToProps,
  { getPost })(Post);

【讨论】:

  • Yippee-Ki-Yay 成功了!十分感谢你的帮助。这让我发疯了。你拯救了我的理智和血压。祝您在 7 月 4 日过得愉快。
猜你喜欢
  • 1970-01-01
  • 2019-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-15
相关资源
最近更新 更多