Javascript initialValues第一次起作用,但页面刷新后会中断页面,请执行REACT/REDUX

Javascript initialValues第一次起作用,但页面刷新后会中断页面,请执行REACT/REDUX,javascript,reactjs,redux,Javascript,Reactjs,Redux,我可以点击编辑评论,它会带我进入评论编辑页面,页面上有该评论的值。问题是,如果我点击刷新,它会破坏页面,并且我会得到未定义的错误注释。现在我知道这是因为状态已经被清除了,但是有没有一种方法可以让我等到状态加载进来 更新:我已修复了刷新时页面中断的问题,但我无法获取初始值以获取注释值。我不确定以后是否有办法设置状态值。我得到了类似于author未定义和\u id未定义的东西,我知道这是因为我正在将commentValue设置为{}。我的问题是,有没有一种方法可以在状态得到正确更新时获得这些值 以下

我可以点击编辑评论,它会带我进入评论编辑页面,页面上有该评论的值。问题是,如果我点击刷新,它会破坏页面,并且我会得到未定义的错误注释。现在我知道这是因为状态已经被清除了,但是有没有一种方法可以让我等到状态加载进来

更新:我已修复了刷新时页面中断的问题,但我无法获取初始值以获取注释值。我不确定以后是否有办法设置状态值。我得到了类似于
author
未定义和
\u id
未定义的东西,我知道这是因为我正在将
commentValue
设置为
{}
。我的问题是,有没有一种方法可以在状态得到正确更新时获得这些值

以下是检查代码:

function mapStateToProps({ posts, auth, user }, ownProps) {
  let commentValue = {};
  const post = posts[ownProps.match.params.id];

  if(!post){
    return commentValue = {};
  }
  if(!posts.comments[ownProps.match.params.comment_id]) {
    return commentValue = {};
  }
  if(posts.comments[ownProps.match.params.comment_id]){
    return commentValue = posts.comments[ownProps.match.params.comment_id];
  }

  return {
    initialValues: commentValue,
    post: posts[ownProps.match.params.id],
    auth: auth.authenticated,
    user: user
  };
}
代码如下:

import React , { Component } from 'react';
import * as actions from '../../actions/comments_actions';
import { bindActionCreators } from 'redux';
import * as actionsPosts from '../../actions/posts_actions';
import * as actionsIndex from '../../actions/index';
import { reduxForm, Field } from 'redux-form';
import {connect} from 'react-redux';
import {Link} from 'react-router-dom';

class EditComment extends Component {
  componentDidMount() {
    const {id, comment_id} = this.props.match.params;
    this.props.getOnePost(id);

    if(this.props.user._id !== this.props.post.comments[comment_id].author.id) {
      this.props.history.replace(`/posts/${id}`);
    }

    if(this.props.auth) {
      this.props.getUser();
    }

  }

  componentWillReceiveProps ({ user: nextUser, history, match, post, auth}) {

    const {user: currentUser} = this.props;
    const { id } = match.params

    if (!currentUser || nextUser !== currentUser) {
    if (nextUser && (nextUser._id !== post.author.id)) {
      history.replace(`/posts/${id}`);
    }
  }
}

  renderField(field) {
    const { meta: {touched, error} } = field;
    const className = `form-group ${touched && error ? 'has-danger' : ''}`;

    return (
      <div className={className}>
        <label><strong>{field.label}:</strong></label>
        <input
          className="form-control"
          type={field.type}
          {...field.input}
        />
        <div className="text-help">
          { touched ? error : ''}
        </div>
      </div>
    )
  }

  onSubmit(values) {
    const {comment_id} = this.props.match.params;

    this.props.editComment(values, comment_id, () => {
      this.props.history.push(`/posts/${id}`);
    });
  }

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

    const {id} = this.props.match.params;

    return (
      <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
        <Field
          label="Comment"
          name="text"
          type="text"
          component={this.renderField}
        />
        <button type="submit" className="btn btn-success">Comment</button>
        <Link to={`/posts/${id}`} className="btn btn-danger">Cancel</Link>
      </form>
    );
  }
}

function validate(values) {
  const errors = {};

  if(!values.comment) {
    errors.comment = "Enter a comment!";
  }

  return errors;
}

function mapStateToProps({ posts, auth, user }, ownProps) {
  console.log(posts[ownProps.match.params.id]);
  const commentValue = posts[ownProps.match.params.id].comments[ownProps.match.params.comment_id];
  console.log(commentValue);
  return {
    initialValues: commentValue,
    post: posts[ownProps.match.params.id],
    auth: auth.authenticated,
    user: user
  };
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({...actions, ...actionsIndex, ...actionsPosts}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(reduxForm({
  validate,
  form: 'editform'
})(EditComment));
import React,{Component}来自'React';
从“../../actions/comments_actions”导入*作为操作;
从“redux”导入{bindActionCreators};
从“../../actions/posts_actions”导入*作为actionsPosts;
从“../../actions/index”导入*作为actionsIndex;
从'redux form'导入{reduxForm,Field};
从'react redux'导入{connect};
从'react router dom'导入{Link};
类EditComment扩展组件{
componentDidMount(){
const{id,comment_id}=this.props.match.params;
this.props.getOnePost(id);
if(this.props.user.\u id!==this.props.post.comments[comment\u id].author.id){
this.props.history.replace(`/posts/${id}`);
}
if(this.props.auth){
this.props.getUser();
}
}
componentWillReceiveProps({user:nextUser,history,match,post,auth}){
const{user:currentUser}=this.props;
const{id}=match.params
如果(!currentUser | | nextUser!==currentUser){
if(nextUser&(nextUser.\u id!==post.author.id)){
替换(`/posts/${id}`);
}
}
}
渲染场(场){
常量{meta:{toucted,error}}=field;
const className=`form group${moved&&error?'has danger':'}`;
返回(
{field.label}:
{触摸?错误:“”
)
}
onSubmit(值){
const{comment_id}=this.props.match.params;
this.props.editComment(值,注释id,()=>{
this.props.history.push(`/posts/${id}`);
});
}
render(){
const{handleSubmit}=this.props;
const{id}=this.props.match.params;
返回(
评论
取消
);
}
}
函数验证(值){
常量错误={};
如果(!values.comment){
errors.comment=“输入注释!”;
}
返回错误;
}
函数mapStateToProps({posts,auth,user},ownProps){
log(posts[ownProps.match.params.id]);
const commentValue=posts[ownProps.match.params.id].comments[ownProps.match.params.comment\u id];
console.log(commentValue);
返回{
initialValues:commentValue,
post:posts[ownProps.match.params.id],
auth:auth.authenticated,
用户:用户
};
}
功能图DispatchToprops(调度){
返回bindActionCreators({…actions,…actionsIndex,…actionsPosts},dispatch);
}
导出默认连接(mapStateToProps、mapDispatchToProps)(reduxForm({
验证
表单:“编辑表单”
})(编辑评论);

听起来好像发生了这样的事情:当您在该URL刷新页面时,您的路由逻辑确保显示此组件,但您的应用程序没有加载此组件所需的数据

这与Dave Ceddia在其帖子中描述的问题基本相同。如果某个组件可能在其所需数据可用之前被呈现,则应编写代码来处理这种情况。有几种方法可以做到这一点,Dave在他的帖子中给出了一些例子

在您的特定情况下,您的
mapState
函数试图取消对某些嵌套状态的引用:

const commentValue = posts[ownProps.match.params.id].comments[ownProps.match.params.comment_id];  

您应该将其分解为两个步骤,并进行防御性检查,以查看首先是否存在具有该ID的帖子,如果存在,是否存在具有该ID的评论。如果没有,您可能希望从
mapState
中为该道具返回
null
undefined
,听起来像是您的路由逻辑正在确保在该URL刷新页面时显示该组件,但您的应用程序没有加载此组件所需的数据

这与Dave Ceddia在其帖子中描述的问题基本相同。如果某个组件可能在其所需数据可用之前被呈现,则应编写代码来处理这种情况。有几种方法可以做到这一点,Dave在他的帖子中给出了一些例子

在您的特定情况下,您的
mapState
函数试图取消对某些嵌套状态的引用:

const commentValue = posts[ownProps.match.params.id].comments[ownProps.match.params.comment_id];  

您应该将其分解为两个步骤,并进行防御性检查,以查看首先是否存在具有该ID的帖子,如果存在,是否存在具有该ID的评论。如果没有,您可能希望从
mapState

为该道具返回
null
undefined
,在markerikson的帮助下,我找到了一个解决方案。在
mapstatetops
中,我做了一些检查并设置了一些初始值,以防状态返回undefined。以下是工作代码:

function mapStateToProps({ posts, auth, user }, ownProps) {
  let commentValue = {};
  const {id, comment_id} = ownProps.match.params;

  if(!posts.comments){
    commentValue = null;
  }
  if(posts[id]){
    if(posts[id] && posts[id].comments[comment_id]){
      commentValue = posts[id].comments[comment_id];
    }
  }

  return {
    initialValues: commentValue,
    post: posts[ownProps.match.params.id],
    auth: auth.authenticated,
    user: user
  };
}

在马克里克森的帮助下,我想出了一个解决办法。在
mapstatetops
中,我做了一些检查并设置了一些初始值,以防状态返回undefined。以下是工作代码:

function mapStateToProps({ posts, auth, user }, ownProps) {
  let commentValue = {};
  const {id, comment_id} = ownProps.match.params;

  if(!posts.comments){
    commentValue = null;
  }
  if(posts[id]){
    if(posts[id] && posts[id].comments[comment_id]){
      commentValue = posts[id].comments[comment_id];
    }
  }

  return {
    initialValues: commentValue,
    post: posts[ownProps.match.params.id],
    auth: auth.authenticated,
    user: user
  };
}

好吧,我会试试看,如果我让它工作或不工作,我会回来的!谢谢你提供的信息!UH不,代码现在仍然有问题。你需要改变我在你的网站上的台词