React antd步骤将子组件重新呈现为父状态更改

时间:2019-02-12 12:46:25

标签: reactjs antd

我有很长的注册表格,已使用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 });
    }
  }
 });
};

用户对象已正确更新,但子组件未正确更新。为什么?

谢谢。

1 个答案:

答案 0 :(得分:0)

要将props传递到state,必须使用getDerivedStateFromProps方法。

在子类中,您可以添加以下内容-这是您的Address组件的示例,您可以通过address从父组件收到props

static getDerivedStateFromProps(props, state) {
   const { address } = props;
   if(address !== state.address) return { address }
}

现在,这里发生的是,如果父组件发送新的props,该函数将检查prop.addressstate.address是否不同-这是子Component状态-并且是否为不同,它将其设置为从props

接收的值

在您的Address类中添加此方法,它应该可以工作