【发布时间】:2017-05-18 20:45:58
【问题描述】:
出于学习目的,我正在用 ReactJS 中的向导编写一个小应用程序。
我为向导创建了一些组件,如下所示;
- 进度条
- 向导
- WizardStepOne
- WizardStepOneForm
- WizardStepTwo
- WizardStepTwoForm
在向导组件中,我包含了用于显示进度的 PorgressBar 组件,并创建了一个 switch 语句来确定每个“StepForm”中包含的按钮的 oneClick 值,以获取值并显示下一个“WizardStepTwoForm”组件。
这一切都很好,完全符合我的预期,但我面临一个问题。在我验证“WizardStepOneForm”之前,我不希望用户能够获得下一个“WizardStepTwoForm”表单。所以我应该如何将状态返回给我的父组件以确定用户是否可以单击到下一个状态。或者,我通过某个状态禁用按钮,直到验证完成,但在这种情况下,用户将无法单击按钮以验证表单。
在提交表单期间,我想将数据发送到 API,调度正在工作,但我只是想知道如何正确解决它,所以我在父级(向导)中的 switch 语句只有在以下情况下才会被触发表格有效。
向导
//.. imports
class Wizard extends React.Component {
constructor(props) {
super(props);
this.state = {
step : 'stepOne',
progression : '0%'
};
this.handleFormSubmit = this.handleFormSubmit.bind(this);
}
componentDidMount() {
const wizard = JSON.parse(localStorage.getItem('wizard'));
if (wizard !== null) {
this.setState({
step: wizard.step,
progression: wizard.progression
});
}
}
componentDidUpdate() {
localStorage.setItem('wizard', JSON.stringify({
step : this.state.step,
progression : this.state.progression
}));
}
handleFormSubmit(e) {
switch (e.target.value) {
case 'stepOne' :
this.setState({
step : 'stepOne',
progression : '0%',
});
break;
case 'stepTwo' :
this.setState({
step : 'stepTwo',
progression : '50%'
});
break;
}
}
/**
*
* Render
* @return {JSX}
*/
render() {
const { step, progression } = this.state;
switch (step) {
case 'stepOne' :
return (
<div>
<Header />
<WizardProgressBar progression={progression} stepOne="active" stepTwo="" />
<WizardStepOne handleFormSubmit={this.handleFormSubmit} />
<Footer/>
</div>
);
break;
case 'stepTwo' :
return (
<div>
<Header />
<WizardProgressBar progression={progression} stepOne="done" stepTwo="active" />
<WizardStepTwo handleFormSubmit={this.handleFormSubmit} />
<Footer/>
</div>
);
break;
}
}
}
export default Wizard;
WizardStepOne
export default class WizardStepOne extends React.Component {
constructor(props) {
super(props);
}
/**
*
* Render
* @return {XML}
*/
render() {
return(
<div className="step-one">
<h1>Step 1</h1>
<WizardStepOneForm handleFormSubmit={this.props.handleFormSubmit} />
</div>
);
}
}
WizardStepForm
//... imports
@connect((store) => {
return {
};
})
export default class WizardStepOneForm extends React.Component {
constructor(props) {
super(props);
this.state = {
formData : {
firstName : '',
lastName : '',
},
formErrors : {
firstName : true,
lastName : true,
},
formErrorMessages : {
firstName : 'some validation message',
lastName : 'some validation message',
},
formButtonEnabled : true,
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleFirstNameChange = this.handleFirstNameChange.bind(this);
this.handleLastNameChange = this.handleLastNameChange.bind(this);
}
componentDidMount() {
const stepOne = JSON.parse(localStorage.getItem('stepOne'));
if (stepOne !== null) {
this.setState({
formData : stepOne.formData,
formErrors : stepOne.formErrors,
formErrorMessages : stepOne.formErrorMessages,
});
}
}
handleFirstNameChange(e) {
let formData = this.state.formData;
let formErrors = this.state.formErrors;
let formErrorMessages = this.state.formErrorMessages;
formData.firstName = e.target.value;
if (!e.target.value) {
formErrors.firstName = true;
} else {
formErrors.firstName = false;
}
this.setState({ formData : formData, formErrors : formErrors, formErrorMessages : formErrorMessages });
localStorage.setItem('stepOne', JSON.stringify({ formData : formData, formErrors : formErrors, formErrorMessages : formErrorMessages }));
}
handleLastNameChange(e) {
let formData = this.state.formData;
let formErrors = this.state.formErrors;
let formErrorMessages = this.state.formErrorMessages;
formData.lastName = e.target.value;
if (!e.target.value) {
formErrors.lastName = true;
} else {
formErrors.lastName = false;
}
this.setState({ formData : formData, formErrors : formErrors, formErrorMessages : formErrorMessages });
localStorage.setItem('stepOne', JSON.stringify({ formData : formData, formErrors : formErrors, formErrorMessages : formErrorMessages }));
}
handleSubmitButton() {
}
handleSubmit(e) {
e.preventDefault();
this.props.dispatch(addUser(this.state.formData));
}
/**
*
* Render
* @return {XML}
*/
render() {
const firstNameError = this.state.formErrors.firstName ? 'error' : '';
const lastNameError = this.state.formErrors.lastName ? 'error' : '';
return(
<form className="step-one-form">
<div className="form-group right">
<div className="form-group__form-row">
<p className={classnames('col-2', firstNameError)}>
<label htmlFor="first_name">First name:</label>
<input type="text" id="firstName" name="fist_name" autoComplete="off" onChange={this.handleFirstNameChange} value={this.state.formData.firstName} />
{ firstNameError ? <FormElementErrorMessage message={this.state.formErrorMessages.firstName} /> : '' }
</p>
<p className={classnames('col-2', lastNameError)}>
<label htmlFor="last_name">Last name:</label>
<input type="text" id="lastName" name="last_name" autoComplete="off" onChange={this.handleLastNameChange} value={this.state.formData.lastName} />
{ lastNameError ? <FormElementErrorMessage message={this.state.formErrorMessages.lastName} /> : '' }
</p>
</div>
</div>
<button disabled={this.state.formButtonEnabled} onClick={this.props.handleFormSubmit} value="stepTwo">Next step</button>
</form>
);
}
}
【问题讨论】:
-
你见过 react-albus github.com/americanexpress/react-albus吗?
-
据我所知,我仍然会遇到同样的问题,因为我的表单验证将在 WizardStepOneForm 组件中完成
标签: javascript forms validation reactjs redux