不更新内部状态

时间:2017-07-13 16:03:43

标签: javascript reactjs redux

我有一个用例,即有一个应该被控制的表单,并且应该预先填充其字段,以便用户可以编辑表单。为此,我所做的是

const mapStateToProps = createStructuredSelector({
  myInfo: makeSelectMyInfo(),
  errorResponse: makeSelectMyInfoErrorResponse()
});

const mapDispatchToPropes = dispatch => ({
  loadMyInfo: () => dispatch(getMyInfo()),
  updateMyInfo: (myInfo, token) => dispatch(updateMyInfo(myInfo, token))
});

class ConfirmPropertyByUser extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      user_info: {
        contact_fname: "",
        contact_lname: "",
        agree_terms_condition: false,
      }
    };
  }
  componentDidMount() {
    this.props.loadMyInfo();
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.myInfo !== this.props.myInfo) {
      console.log("object", Object.values(nextProps.myInfo));
      this.setState(state => ({
        user_info: {
          ...state.user_info,
          contact_fname: nextProps.myInfo.contact_fname,
          contact_lname: nextProps.myInfo.contact_lname,
        }
      }));
    }
  }

  handleChange = e => {
    this.setState({
      user_info: { ...this.state.user_info, [e.target.name]: e.target.value }
    });
  };

  handleUserTerms = e =>
    this.setState({
      user_info: {
        ...this.state.user_info,
        agree_terms_condition: e.target.checked
      }
    });

  handleSubmit = e => {
    e.preventDefault();
    this.props.updateMyInfo(this.state.user_info, this.props.match.params.id);
  };

  render() {
    const { errorResponse } = this.props;
    const { user_info } = this.state;
    let message;
    if (errorResponse && typeof errorResponse === "string") {
      message = <Notification message={errorResponse} timeout={5000} />;
    }
    return (
      <div className="container">
        {message && message}
        <div className="card card-lg">
          <h1>Register</h1>
          <form onSubmit={this.handleSubmit}>
              <div className="form-group">
                <label>First Name</label>
                <input
                  type="text"
                  name="contact_fname"
                  className="form-control"
                  value={user_info && user_info.contact_fname}
                  onChange={this.handleChange}
                />
              </div>
              <div className="form-group">
                <label>Last Name</label>
                <input
                  type="text"
                  name="contact_lname"
                  className="form-control"
                  value={user_info && user_info.contact_lname}
                  onChange={this.handleChange}
                />
              </div>
              <div className="form-group">
                  <input
                    className="custom-control-input"
                    type="checkbox"
                    onChange={this.handleUserTerms}
                  />
              </div>
              <button
                className="btn btn-default btn-block btn-lg"
                disabled={
                  !user_info.password || !user_info.agree_terms_condition
                }
              >
                Submit Details
              </button>
            </fieldset>
          </form>
        </div>
      </div>
    );
  }
}

export default connect(mapStateToProps, mapDispatchToPropes)(
  ConfirmPropertyByUser
);

我正在使用redux并更新内部状态。但是我听说过在使用redux时它不需要更新内部状态。如何在不更新内部状态的情况下解决以下问题?有人可以帮帮我吗?

1 个答案:

答案 0 :(得分:1)

你正在做的事似乎没问题。根据Redux常见问题解答,there's nothing wrong with using component state in a Redux app。对于表单来说,需要同时拥有&#34;原创&#34;一组价值观和一个正在进行的工作&#34;复制的一组值,它取决于&#34; WIP&#34;值存储在Redux或React组件中。

为了它的价值,我确实展示了一些关于&#34; WIP&#34;在我的博客文章Practical Redux, Part 8: Form Draft Data Management中将状态转换为Redux,这可能是一个有用的参考。但是,总的来说,这里的代码看起来很好 - 你在componentWillReceiveProps的构造函数中正确地将道具复制到状态,你所遵循的概念方法是完美的细

一个小的风格建议:我通常建议人们使用mapDispatch参数的对象简写语法。在您的情况下,它看起来像:

const actions = {loadMyInfo : getMyInfo, updateMyInfo : updateMyInfo};

// later
export default connect(mapState, actions)(ConfirmPropertyByUser);