当用户提交表单时,我正在检查某个字段的值是否已更改。如果有,那么我正在显示确认模式。如果用户在模态中单击“是”,则模态组件在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)
答案 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>
);
};
}