触发在componentWillReceiveProps中提交的redux表单

时间:2018-10-12 20:17:05

标签: javascript reactjs react-redux

当用户提交表单时,我正在检查某个字段的值是否已更改。如果有,那么我正在显示确认模式。如果用户在模态中单击“是”,则模态组件在redux中将“ dismissedSubTypeChangeWarning”道具设置为true。

在componentWillReceiveProps内部,我监听此道具的任何更改。如果其值为true,我想触发表单的提交。我按照https://redux-form.com/6.5.0/examples/remotesubmit/上的说明进行了配置。

该调度调用永远不会触发,因为在控制台中,我看到“检测到的关闭”,然后什么也没有。我希望在“检测到的关闭”之后看到“ submitForm方法”。

我将下面的代码压缩为最基本的版本以显示问题。运行代码时,我在控制台中看不到任何错误。

我找到了一个使用refs的解决方案(请参见注释行),但伪造单击似乎不是一个好习惯。

class ChangeEditForm extends React.Component {
    componentWillReceiveProps (nextProps) {
        if (nextProps.dismissedSubTypeChangeWarning) {
        console.log('detected dismiss')
        this.props.toggleDismissedSubTypeChangeWarning()
        this.props.dispatch(submit('changeEdit'))
        // this.refs.submit.click()
        }
    }

    render () {
        <form onSubmit={this.props.handleSubmit(this.props.submitForm)}>
            <button type='submit' ref='submit'>Save</button>
        </form>
    }
}

const handlers = {
    submitForm: props => (formValues) => {
        console.log('submitForm method')
        if ((formValues.subtype !== props.initialValues.subtype) && !props.dismissedSubTypeChangeWarning) {
            console.log('show warning')
            props.toggleSubTypeChangeConfirmModal()
        } else {
            console.log('submitting form')
        }
    }
}

export function mapStateToProps (state, props) {
    return {
        dismissedSubTypeChangeWarning: state.ui.dismissedSubTypeChangeWarning
    }
}

export default compose(
    pure,
    reduxForm({
        form: 'changeEdit',
        onSubmit: handlers.submitForm
    }),
    connect(mapStateToProps, null),
    withRouter,
    withHandlers(handlers)
)(ChangeEditForm)  

1 个答案:

答案 0 :(得分:1)

我仍然认为您已经使表格提交复杂化了。

如评论中所述,表单提交一次,检查一次值,如果值不同则弹出窗口生成,在弹出窗口中确认更新值,否则取消关闭模式并按原样保留表单。

通过创建HOC,我们可以控制模式和表单,而无需在弹出窗口确认时重新提交表单。

工作示例:https://codesandbox.io/s/lxv9o1nxzl

容器/ChangeNameHOC.js

import React, { Component } from "react";
import { connect } from "react-redux";
import { reset } from "redux-form";
import { updateUser } from "../actions";
import { Values } from "redux-form-website-template";
import ChangeNameForm from "./ChangeNameForm";
import ShowModal from "../components/ShowModal";
import CurrentStore from "../containers/CurrentStore";

class ChangeNameHOC extends Component {
  state = {
    modalIsOpen: false,
    formProps: {}
  };

  openModal = () => this.setState({ modalIsOpen: true });

  closeModal = () => this.setState({ modalIsOpen: false });

  validateFormValues = formProps => {
    const { firstName, lastName } = this.props;
    const nextFirstName = formProps.firstName;
    const nextLastName = formProps.lastName;

    if (firstName !== nextFirstName || lastName !== nextLastName) {
      this.setState({ modalIsOpen: true, formProps });
    }
  };

  handleSubmit = () => {
    this.setState({ modalIsOpen: false }, () => {
      this.props.updateUser(this.state.formProps);
      this.props.reset("ChangeNameForm");
    });
  };

  render = () => (
    <div style={{ padding: "0px 20px" }}>
      <ShowModal
        {...this.state}
        {...this.props}
        afterOpenModal={this.afterOpenModal}
        openModal={this.openModal}
        closeModal={this.closeModal}
        handleSubmit={this.handleSubmit}
      />
      <ChangeNameForm validateFormValues={this.validateFormValues} />
      <CurrentStore />
      <Values form="ChangeNameForm" />
    </div>
  );
}

export default connect(
  state => ({
    firstName: state.user.firstName,
    lastName: state.user.lastName
  }),
  { updateUser, reset }
)(ChangeNameHOC);

containers / ChangeNameForm.js

import React from "react";
import { Field, reduxForm } from "redux-form";
import RenderField from "../components/RenderField";

const isRequired = value => (!value ? "Required" : undefined);

const ChangeNameForm = ({
  handleSubmit,
  reset,
  submitting,
  validateFormValues
}) => (
  <form onSubmit={handleSubmit(validateFormValues)}>
    <Field
      className="uk-input"
      label="First Name"
      name="firstName"
      component={RenderField}
      type="text"
      placeholder="First Name"
      validate={[isRequired]}
    />
    <Field
      className="uk-input"
      label="Last Name"
      name="lastName"
      component={RenderField}
      type="text"
      placeholder="Last Name"
      validate={[isRequired]}
    />
    <button
      className="uk-button uk-button-primary"
      type="submit"
      disabled={submitting}
      style={{ marginBottom: 20 }}
    >
      Submit
    </button>
    <div style={{ float: "right" }}>
      <button
        className="uk-button uk-button-danger"
        type="button"
        disabled={submitting}
        onClick={reset}
        style={{ marginBottom: 20 }}
      >
        Reset
      </button>
    </div>
  </form>
);

export default reduxForm({
  form: "ChangeNameForm"
})(ChangeNameForm);

components / ShowModal.js

import React, { PureComponent } from "react";
import Modal from "react-modal";

const customStyles = {
  content: {
    minWidth: "400px",
    top: "50%",
    left: "50%",
    right: "auto",
    bottom: "auto",
    marginRight: "-50%",
    transform: "translate(-50%, -50%)"
  }
};

Modal.setAppElement("#root");

export default class ShowModal extends PureComponent {
  showChange = (name, prevName, nextName) => (
    <div>
      {name}: <strong>{prevName}</strong> to <strong>{nextName}</strong>
    </div>
  );

  render = () => {
    const { firstName, lastName } = this.props;
    const { firstName: nextFirstName } = this.props.formProps;
    const { lastName: nextLastName } = this.props.formProps;

    return (
      <div>
        <Modal
          isOpen={this.props.modalIsOpen}
          onAfterOpen={this.props.afterOpenModal}
          onRequestClose={this.props.closeModal}
          style={customStyles}
          contentLabel="Are you sure?"
        >
          <h3>Are you sure you want to update?</h3>
          <div style={{ marginBottom: 20 }}>
            {firstName !== nextFirstName
              ? this.showChange("FirstName", firstName, nextFirstName)
              : null}
            {lastName !== nextLastName
              ? this.showChange("LastName", lastName, nextLastName)
              : null}
          </div>
          <button
            style={{ float: "left" }}
            className="uk-button uk-button-primary"
            onClick={this.props.handleSubmit}
          >
            confirm
          </button>
          <button
            style={{ float: "right" }}
            className="uk-button uk-button-danger"
            onClick={this.props.closeModal}
          >
            cancel
          </button>
        </Modal>
      </div>
    );
  };
}