【发布时间】: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) -
不幸的是,它导致了另一个未定义的属性值。