initialValues第一次工作,但页面刷新后打破页面,REACT / REDUX

时间:2017-07-06 16:46:49

标签: javascript reactjs redux

我可以点击编辑评论,它会将我带到评论编辑页面,其中包含该评论的值。问题是,如果我点击刷新它打破了页面,我得到错误评论未定义。现在我知道这是因为国家已被抹去,但有没有办法解决这个问题,我可以等到国家加载或等等?

更新:我已经修复了破解刷新的页面但我无法获取initialValues来获取评论值。我不确定以后是否有办法设置状态值。我收到author未定义和_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));

2 个答案:

答案 0 :(得分:0)

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

这基本上与Dave Ceddia在帖子Watch Out for Undefined State中描述的问题相同。如果有可能在您需要的数据可用之前呈现其中一个组件,则应编写代码来处理该情况。有几种方法可以做到这一点,Dave在他的帖子中展示了一些例子。

在您的特定情况下,您的mapState函数正在尝试取消引用一些非常嵌套的状态:

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

您应该将其分解为几个步骤,然后进行防御性检查以查看是否首先存在具有该ID的帖子,如果存在,则是否存在具有该ID的评论。如果他们不这样做,您可能希望从null返回undefinedmapState该道具。

答案 1 :(得分:0)

在markerikson的帮助下,我能够找到解决方案。在mapStateToProps中,我做了一些检查,并在状态将返回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
  };
}