我有很长的注册表格,已使用AntD的步骤组件将其分为几部分。
//定义的子表单组件
steps = {
basicInfo: {
title: 'Basic Info',
content: (
<BasicInfoForm
form={this.props.form}
user={this.user}
/>
),
},
addresses: {
title: 'Addresses',
content: (
<Address
form={this.props.form}
addresses={this.user.addresses}
/>
),
},
contactInfo: {
title: 'Contact Info',
content: (
<PhoneForm
form={this.props.form}
contactInfo={this.user.contactInfo}
/>
),
},
}
//配置这些子表单组件的表单
<Form onSubmit={handleSubmit} className="add-edit-user-form">
<Fragment>
<Steps progressDot current={this.state.currentStep}>
{Object.keys(steps).map((key, index) => {
return <Step title={steps && steps[index] ? steps[index].title : null} key={index} />;
})}
</Steps>
<div className={styles['steps-content']}>{steps && steps[currentStep] ? steps[currentStep].content : null}</div>
<div className="steps-action">
{currentStep > 0 && (
<Button style={{ marginLeft: 8 }} onClick={() => this.prev()}>Previous</Button>
)}
{currentStep < steps.length - 1 && (
<Button type="primary" htmlType="submit">Next</Button>
)}
{currentStep === steps.length - 1 && (
<Button type="primary" htmlType="submit">Done</Button>
)}
</div>
</Fragment>
</Form>
//来自父对象的用户对象的类变量。
user = this.props.user ? this.props.user : undefined;
//子组件
interface IAddressFormProps {
form: WrappedFormUtils;
addresses: IAddress[];
fieldName: string;
}
class Address extends Component<IAddressFormProps> {
totalAddresses: any = this.props.addresses && this.props.addresses ?
this.props.addresses : ([{}] as IAddress[]);
state = {
totalAddresses: this.totalAddresses ? this.totalAddresses : ([] as IAddress[]),
};
addAddress = () => {
this.setState((prevState: any) => ({
totalAddresses: [...prevState.totalAddresses, { lineOne: '', lineTwo: '', lineThree: '', city: '', state: '', zip: '', type: '' }],
}));
};
removeAddress = (index: number) => {
this.setState({
totalAddresses: this.state.totalAddresses.filter((item: IAddress, addressIndex: number) => index !== addressIndex),
});
};
render() {
const { getFieldDecorator } = this.props.form;
const fieldName = this.props.fieldName;
return (
<Fragment>
{this.state.totalAddresses.map((item: IAddress, index: number) => {
return (
<Row key={'container-' + index} type="flex" justify="start" gutter={16}>
<Col span={6}>
<Form.Item label="Type" key={'type-' + index}>
{getFieldDecorator(`${fieldName}[${index}].type`, {
initialValue: item.type,
rules: [{ required: true, message: 'Please input address type!' }],
})(
<Select placeholder="Type">
<Option value="Mailing">Mailing</Option>
<Option value="Business">Business</Option>
<Option value="Home">Home</Option>
<Option value="Other">Other</Option>
</Select>
)}
</Form.Item>
<Form.Item label="Line One" key={'lineOne-' + index}>
{getFieldDecorator(`${fieldName}[${index}].lineOne`, {
initialValue: item.lineOne,
rules: [{ required: true, message: 'Please input line one!' }],
})(<Input placeholder="Line One" />)}
</Form.Item>
<Form.Item label="Line Two" key={'lineTwo-' + index}>
{getFieldDecorator(`${fieldName}[${index}].lineTwo`, {
initialValue: item.lineTwo,
rules: [{ required: false, message: 'Please input line two!' }],
})(<Input placeholder="Line Two" />)}
</Form.Item>
<Form.Item label="Line Three" key={'lineThree-' + index}>
{getFieldDecorator(`${fieldName}[${index}].lineThree`, {
initialValue: item.lineThree,
rules: [{ required: false, message: 'Please input line three!' }],
})(<Input placeholder="Line Three" />)}
</Form.Item>
</Col>
<Col span={9}>
<Form.Item label="City" key={'city-' + index}>
{getFieldDecorator(`${fieldName}[${index}].city`, {
initialValue: item.city,
rules: [{ required: true, message: 'Please input city!' }],
})(<Input placeholder="City" />)}
</Form.Item>
<Form.Item label="State" key={'state-' + index}>
{getFieldDecorator(`${fieldName}[${index}].state`, {
initialValue: item.state,
rules: [{ required: true, message: 'Please input state!' }],
})(<Input placeholder="State" />)}
</Form.Item>
<Form.Item label="Zip" key={'zip-' + index}>
{getFieldDecorator(`${fieldName}[${index}].zip`, {
initialValue: item.zip,
rules: [{ required: true, message: 'Please input zip!' }],
})(<Input placeholder="Zip" />)}
</Form.Item>
</Col>
<Col span={4}>
<Button onClick={() => this.removeAddress(index)}>Remove</Button>
</Col>
</Row>
);
})}
<Button onClick={() => this.addAddress()}>Add address</Button>
</Fragment>
);
}
}
我要在整个步骤中保持用户对象的状态,意味着来回移动。 在表单提交时,更新用户对象。
next = (addEditUser: MutationFn<any, any>) => {
const form = this.props.form;
form.validateFields(async (err: any, values: any) => {
if (err) {
return false;
}
values.id = this.userId;
let variables = this.parentId ? { user: values, parentId: this.parentId } : { user: values };
const result = await addEditUser({ variables: variables });
if (result && result.data) {
if (this.state.currentStep === this.state.steps.length - 1) {
this.props.history.push('/user');
} else {
this.user = Object.assign(this.user, values);
const currentStep = this.state.currentStep + 1;
this.setState({ currentStep });
}
}
});
};
用户对象已正确更新,但子组件未正确更新。为什么?
谢谢。
答案 0 :(得分:0)
要将props
传递到state
,必须使用getDerivedStateFromProps
方法。
在子类中,您可以添加以下内容-这是您的Address
组件的示例,您可以通过address
从父组件收到props
static getDerivedStateFromProps(props, state) {
const { address } = props;
if(address !== state.address) return { address }
}
现在,这里发生的是,如果父组件发送新的props
,该函数将检查prop.address
与state.address
是否不同-这是子Component状态-并且是否为不同,它将其设置为从props
在您的Address
类中添加此方法,它应该可以工作