Javascript 获取错误bundle.js:39454未捕获类型错误:无法读取属性';电子邮件';使用MERN堆栈定义未定义的
我正在使用MERN堆栈,似乎不明白为什么会发生这种情况。我有一个显示得很好的帖子列表。当我点击帖子时,我在控制台中得到Javascript 获取错误bundle.js:39454未捕获类型错误:无法读取属性';电子邮件';使用MERN堆栈定义未定义的,javascript,node.js,mongodb,reactjs,Javascript,Node.js,Mongodb,Reactjs,我正在使用MERN堆栈,似乎不明白为什么会发生这种情况。我有一个显示得很好的帖子列表。当我点击帖子时,我在控制台中得到无法读取未定义的属性“email”。但是如果我点击“刷新”,一切正常,那篇文章会显示所有的工作问题 我能够确定我的renderComments()函数的错误。这就是一切都显示为未定义的地方 编辑:我想我知道发生了什么,但我不知道为什么会发生。在渲染之前,在array.map函数中创建的注释仅为注释ID。仅当组件渲染注释时,注释才为实际完整对象及其所有属性。我将发布后端,以显示我是
无法读取未定义的属性“email”
。但是如果我点击“刷新”,一切正常,那篇文章会显示所有的工作问题
我能够确定我的renderComments()
函数的错误。这就是一切都显示为未定义的地方
编辑:我想我知道发生了什么,但我不知道为什么会发生。在渲染之前,在array.map函数中创建的注释仅为注释ID。仅当组件渲染注释时,注释才为实际完整对象及其所有属性。我将发布后端,以显示我是如何获得帖子上的评论以帮助解决问题的
它被要求在array.map函数之前显示post的console.log。由于这确实指出了我在编辑中所说的话,我将继续并在下面展示以提供帮助
发布管理员评论:
exports.getOnePost = function(req, res, next) {
Posts.findById(req.params.id).populate("comments").exec(function(err, foundPost) {
if(err) {
return next(err);
} else {
res.json(foundPost);
}
});
}
var mongoose = require("mongoose");
const Schema = mongoose.Schema;
var postsSchema = new Schema({
title: String,
createdAt: {type: Date, default: Date.now},
content: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
email: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "comments"
}
]
});
var Posts = mongoose.model("posts", postsSchema);
module.exports = Posts;
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { bindActionCreators } from 'redux';
import * as actions from '../../actions/posts_actions';
import * as actionsIndex from '../../actions/index';
import * as actionsComments from '../../actions/comments_actions';
class ShowPosts extends Component {
constructor(props) {
super(props);
this.onDeleteClick = this.onDeleteClick.bind(this);
this.deleteComment = this.deleteComment.bind(this);
}
componentDidMount() {
const {id} = this.props.match.params;
this.props.getOnePost(id);
if(this.props.auth) {
this.props.getUser();
}
}
renderButtons() {
const { post } = this.props;
if(!this.props.user) {
return ( <div></div> );
}
if(this.props.auth) {
if(this.props.user._id === post.author.id) {
return (
<div>
<button
onClick={this.onDeleteClick}
className="btn btn-danger"
>
Delete
</button>
<Link
to={`/posts/${post._id}/edit`}
className="btn btn-success"
>
Edit
</Link>
</div>
)
}
} else {
return (
<div></div>
)
}
}
renderCommentsButtons(comment) {
const { post, user, auth } = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id) {
return (
<div>
<button
onClick={() => this.deleteComment(comment)}
className="btn btn-xs btn-danger">
Delete
</button>
<Link
to={`/posts/${post._id}/comments/${comment._id}/edit`}
className="btn btn-xs btn-warning">
Edit
</Link>
</div>
)
}
}
}
renderComments() {
const { post } = this.props;
return post.comments.map((comment) => {
return (
<li className="list-group-item" key={comment._id}>
<div>
{comment.text} : {comment.author.email}
</div>
{this.renderCommentsButtons(comment)}
</li>
);
});
}
deleteComment(comment) {
const {id} = this.props.match.params;
const {user, post, auth} = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id){
console.log(comment._id, '-', post._id);
// this.props.deleteComments(id, comment._id, () => {
// this.props.history.push(`/posts/${post._id}`);
// });
}
}
}
onDeleteClick() {
const {id} = this.props.match.params;
if(!this.props.user) {
return (<div></div>);
}
if(this.props.auth) {
if(this.props.user._id === this.props.post.author.id) {
this.props.deletePost(id, () => {
this.props.history.push("/posts");
});
}
}
}
render() {
const { post } = this.props;
if (!post) {
return <div> Loading...No Post</div>;
}
return (
<div>
<Link className="btn btn-primary" to="/posts">Back To Post</Link>
<h3>{post.title}</h3>
<p>{post.content}</p>
<p>created by: {post.author.email}</p>
<ul className="list-group">
{this.renderComments()}
</ul>
{this.renderButtons()}
<Link
className="btn btn-warning"
to={`/posts/${post._id}/comments/new`}>
Comment
</Link>
</div>
);
}
}
function mapStateToProps({ posts, auth, user }, ownProps) {
return {
post: posts[ownProps.match.params.id],
user: user,
auth: auth.authenticated
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({...actions, ...actionsIndex, ...actionsComments}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(ShowPosts);
exports.getAllPosts = function(req, res, next) {
Posts.find({}, function(err, posts) {
if(err) {
return next(err);
} else {
res.json(posts);
}
});
}
exports.getAllPosts = function(req, res, next) {
Posts.find({}).populate("comments").exec(function(err, posts) {
if(err) {
return next(err);
} else {
res.json(posts);
}
});
}
var mongoose = require("mongoose");
const Schema = mongoose.Schema;
var postsSchema = new Schema({
title: String,
createdAt: {type: Date, default: Date.now},
content: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
email: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "comments"
}
]
});
var Posts = mongoose.model("posts", postsSchema);
module.exports = Posts;
发布和评论模式:
exports.getOnePost = function(req, res, next) {
Posts.findById(req.params.id).populate("comments").exec(function(err, foundPost) {
if(err) {
return next(err);
} else {
res.json(foundPost);
}
});
}
var mongoose = require("mongoose");
const Schema = mongoose.Schema;
var postsSchema = new Schema({
title: String,
createdAt: {type: Date, default: Date.now},
content: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
email: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "comments"
}
]
});
var Posts = mongoose.model("posts", postsSchema);
module.exports = Posts;
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { bindActionCreators } from 'redux';
import * as actions from '../../actions/posts_actions';
import * as actionsIndex from '../../actions/index';
import * as actionsComments from '../../actions/comments_actions';
class ShowPosts extends Component {
constructor(props) {
super(props);
this.onDeleteClick = this.onDeleteClick.bind(this);
this.deleteComment = this.deleteComment.bind(this);
}
componentDidMount() {
const {id} = this.props.match.params;
this.props.getOnePost(id);
if(this.props.auth) {
this.props.getUser();
}
}
renderButtons() {
const { post } = this.props;
if(!this.props.user) {
return ( <div></div> );
}
if(this.props.auth) {
if(this.props.user._id === post.author.id) {
return (
<div>
<button
onClick={this.onDeleteClick}
className="btn btn-danger"
>
Delete
</button>
<Link
to={`/posts/${post._id}/edit`}
className="btn btn-success"
>
Edit
</Link>
</div>
)
}
} else {
return (
<div></div>
)
}
}
renderCommentsButtons(comment) {
const { post, user, auth } = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id) {
return (
<div>
<button
onClick={() => this.deleteComment(comment)}
className="btn btn-xs btn-danger">
Delete
</button>
<Link
to={`/posts/${post._id}/comments/${comment._id}/edit`}
className="btn btn-xs btn-warning">
Edit
</Link>
</div>
)
}
}
}
renderComments() {
const { post } = this.props;
return post.comments.map((comment) => {
return (
<li className="list-group-item" key={comment._id}>
<div>
{comment.text} : {comment.author.email}
</div>
{this.renderCommentsButtons(comment)}
</li>
);
});
}
deleteComment(comment) {
const {id} = this.props.match.params;
const {user, post, auth} = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id){
console.log(comment._id, '-', post._id);
// this.props.deleteComments(id, comment._id, () => {
// this.props.history.push(`/posts/${post._id}`);
// });
}
}
}
onDeleteClick() {
const {id} = this.props.match.params;
if(!this.props.user) {
return (<div></div>);
}
if(this.props.auth) {
if(this.props.user._id === this.props.post.author.id) {
this.props.deletePost(id, () => {
this.props.history.push("/posts");
});
}
}
}
render() {
const { post } = this.props;
if (!post) {
return <div> Loading...No Post</div>;
}
return (
<div>
<Link className="btn btn-primary" to="/posts">Back To Post</Link>
<h3>{post.title}</h3>
<p>{post.content}</p>
<p>created by: {post.author.email}</p>
<ul className="list-group">
{this.renderComments()}
</ul>
{this.renderButtons()}
<Link
className="btn btn-warning"
to={`/posts/${post._id}/comments/new`}>
Comment
</Link>
</div>
);
}
}
function mapStateToProps({ posts, auth, user }, ownProps) {
return {
post: posts[ownProps.match.params.id],
user: user,
auth: auth.authenticated
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({...actions, ...actionsIndex, ...actionsComments}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(ShowPosts);
exports.getAllPosts = function(req, res, next) {
Posts.find({}, function(err, posts) {
if(err) {
return next(err);
} else {
res.json(posts);
}
});
}
exports.getAllPosts = function(req, res, next) {
Posts.find({}).populate("comments").exec(function(err, posts) {
if(err) {
return next(err);
} else {
res.json(posts);
}
});
}
var mongoose = require("mongoose");
const Schema = mongoose.Schema;
var postsSchema = new Schema({
title: String,
createdAt: {type: Date, default: Date.now},
content: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
email: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "comments"
}
]
});
var Posts = mongoose.model("posts", postsSchema);
module.exports = Posts;
展示后页面:
exports.getOnePost = function(req, res, next) {
Posts.findById(req.params.id).populate("comments").exec(function(err, foundPost) {
if(err) {
return next(err);
} else {
res.json(foundPost);
}
});
}
var mongoose = require("mongoose");
const Schema = mongoose.Schema;
var postsSchema = new Schema({
title: String,
createdAt: {type: Date, default: Date.now},
content: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
email: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "comments"
}
]
});
var Posts = mongoose.model("posts", postsSchema);
module.exports = Posts;
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { bindActionCreators } from 'redux';
import * as actions from '../../actions/posts_actions';
import * as actionsIndex from '../../actions/index';
import * as actionsComments from '../../actions/comments_actions';
class ShowPosts extends Component {
constructor(props) {
super(props);
this.onDeleteClick = this.onDeleteClick.bind(this);
this.deleteComment = this.deleteComment.bind(this);
}
componentDidMount() {
const {id} = this.props.match.params;
this.props.getOnePost(id);
if(this.props.auth) {
this.props.getUser();
}
}
renderButtons() {
const { post } = this.props;
if(!this.props.user) {
return ( <div></div> );
}
if(this.props.auth) {
if(this.props.user._id === post.author.id) {
return (
<div>
<button
onClick={this.onDeleteClick}
className="btn btn-danger"
>
Delete
</button>
<Link
to={`/posts/${post._id}/edit`}
className="btn btn-success"
>
Edit
</Link>
</div>
)
}
} else {
return (
<div></div>
)
}
}
renderCommentsButtons(comment) {
const { post, user, auth } = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id) {
return (
<div>
<button
onClick={() => this.deleteComment(comment)}
className="btn btn-xs btn-danger">
Delete
</button>
<Link
to={`/posts/${post._id}/comments/${comment._id}/edit`}
className="btn btn-xs btn-warning">
Edit
</Link>
</div>
)
}
}
}
renderComments() {
const { post } = this.props;
return post.comments.map((comment) => {
return (
<li className="list-group-item" key={comment._id}>
<div>
{comment.text} : {comment.author.email}
</div>
{this.renderCommentsButtons(comment)}
</li>
);
});
}
deleteComment(comment) {
const {id} = this.props.match.params;
const {user, post, auth} = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id){
console.log(comment._id, '-', post._id);
// this.props.deleteComments(id, comment._id, () => {
// this.props.history.push(`/posts/${post._id}`);
// });
}
}
}
onDeleteClick() {
const {id} = this.props.match.params;
if(!this.props.user) {
return (<div></div>);
}
if(this.props.auth) {
if(this.props.user._id === this.props.post.author.id) {
this.props.deletePost(id, () => {
this.props.history.push("/posts");
});
}
}
}
render() {
const { post } = this.props;
if (!post) {
return <div> Loading...No Post</div>;
}
return (
<div>
<Link className="btn btn-primary" to="/posts">Back To Post</Link>
<h3>{post.title}</h3>
<p>{post.content}</p>
<p>created by: {post.author.email}</p>
<ul className="list-group">
{this.renderComments()}
</ul>
{this.renderButtons()}
<Link
className="btn btn-warning"
to={`/posts/${post._id}/comments/new`}>
Comment
</Link>
</div>
);
}
}
function mapStateToProps({ posts, auth, user }, ownProps) {
return {
post: posts[ownProps.match.params.id],
user: user,
auth: auth.authenticated
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({...actions, ...actionsIndex, ...actionsComments}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(ShowPosts);
exports.getAllPosts = function(req, res, next) {
Posts.find({}, function(err, posts) {
if(err) {
return next(err);
} else {
res.json(posts);
}
});
}
exports.getAllPosts = function(req, res, next) {
Posts.find({}).populate("comments").exec(function(err, posts) {
if(err) {
return next(err);
} else {
res.json(posts);
}
});
}
var mongoose = require("mongoose");
const Schema = mongoose.Schema;
var postsSchema = new Schema({
title: String,
createdAt: {type: Date, default: Date.now},
content: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "user"
},
email: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "comments"
}
]
});
var Posts = mongoose.model("posts", postsSchema);
module.exports = Posts;
import React,{Component}来自'React';
从'react redux'导入{connect};
从'react router dom'导入{Link};
从“redux”导入{bindActionCreators};
从“../../actions/posts_actions”导入*作为操作;
从“../../actions/index”导入*作为actionsIndex;
从“../../actions/comments_actions”导入*作为actions注释;
类ShowPosts扩展组件{
建造师(道具){
超级(道具);
this.onDeleteClick=this.onDeleteClick.bind(this);
this.deleteComent=this.deleteComent.bind(this);
}
componentDidMount(){
const{id}=this.props.match.params;
this.props.getOnePost(id);
if(this.props.auth){
this.props.getUser();
}
}
renderButtons(){
const{post}=this.props;
如果(!this.props.user){
返回();
}
if(this.props.auth){
if(this.props.user.\u id==post.author.id){
返回(
删除
编辑
)
}
}否则{
返回(
)
}
}
renderCommentsButtons(注释){
const{post,user,auth}=this.props;
如果(!用户){
返回();
}
if(auth){
if(user.\u id==comment.author.id){
返回(
this.deleteComment(comment)}
className=“btn btn xs btn危险”>
删除
编辑
)
}
}
}
renderComments(){
const{post}=this.props;
返回post.comments.map((comment)=>{
返回(
{comment.text}:{comment.author.email}
{this.renderCommentsButtons(comment)}
);
});
}
删除评论(评论){
const{id}=this.props.match.params;
const{user,post,auth}=this.props;
如果(!用户){
返回();
}
if(auth){
if(user.\u id==comment.author.id){
日志(comment.\u id,'-',post.\u id);
//this.props.deleteComments(id,comment.\u id,()=>{
//this.props.history.push(`/posts/${post.\u id}`);
// });
}
}
}
onDeleteClick(){
const{id}=this.props.match.params;
如果(!this.props.user){
返回();
}
if(this.props.auth){
if(this.props.user.\u id==this.props.post.author.id){
this.props.deletePost(id,()=>{
this.props.history.push(“/posts”);
});
}
}
}
render(){
const{post}=this.props;
如果(!post){
返回加载…没有职位;
}
返回(
回到岗位
{post.title}
{post.content}
创建人:{post.author.email}
{this.renderComments()}
{this.renderButtons()}
评论
);
}
}
函数mapStateToProps({posts,auth,user},ownProps){
返回{
post:posts[ownProps.match.params.id],
用户:用户,,
auth:auth.authenticated
};
}
功能图DispatchToprops(调度){
返回bindActionCreators({…操作,…操作索引,…操作注释},调度);
}
导出默认连接(mapStateToProps、mapDispatchToProps)(ShowPosts);
发布
import React , { Component } from 'react';
import * as actions from '../../actions/posts_actions';
import {connect} from 'react-redux';
import {Link} from 'react-router-dom';
import _ from 'lodash';
class Posts extends Component {
componentDidMount() {
this.props.getAllPosts();
}
renderPosts() {
return _.map(this.props.posts, post => {
return (
<Link to={`/posts/${post._id}`} key={post._id}>
<li className="list-group-item">
{post.title}
</li>
</Link>
)
});
}
render() {
return (
<div>
<div className="text-xs-right">
<Link className="btn btn-primary" to="/posts/new">
Add a Post
</Link>
</div>
<h3>Posts</h3>
<ul className="list-group">
{this.renderPosts()}
</ul>
</div>
);
}
}
function mapStateToProps(state) {
return {
posts: state.posts
};
}
export default connect(mapStateToProps, actions)(Posts);
import React,{Component}来自'React';
从“../../actions/posts_actions”导入*作为操作;
从'react redux'导入{connect};
从'react router dom'导入{Link};
从“lodash”进口;
类Posts扩展组件{
componentDidMount(){
this.props.getAllPosts();
}
renderPosts(){
return>map(this.props.posts,post=>{
返回(
{post.title}
)
});
}
render(){
返回(
添加帖子
帖子
{this.renderPosts()}
);
}
}
函数MapStateTops(状态){
返回{
职位:state.posts
};
}
导出默认连接(MapStateTrops、actions)(POST);
这是一个后端问题。如编辑中所述,第一次呈现的帖子只有注释ID,而不是完整的注释对象。我相信最初的帖子来自于posts[ownProps.match.params.id]
,而我们所做的只是从客户端的帖子中获取单一的帖子
如果您查看后端,我会将注释存储为objectid,然后再填充t