当redux store中的值发生变化时,如何更新formik中的特定表单字段?

Posted

技术标签:

【中文标题】当redux store中的值发生变化时,如何更新formik中的特定表单字段?【英文标题】:How to update specific form field in formik when value changes in redux store? 【发布时间】:2020-06-08 02:15:38 【问题描述】:

我在我的反应应用程序中使用 formik。我已经从一个状态初始化了所有表单值。但是如果 redux 商店中的道具发生变化,我想更新一个特定的表单字段。下面是我的formik表单:

<Formik
initialValues=this.state.branchData
enableReinitialize=true
onSubmit=this.formSubmit >
( values, setFieldValue ) => (
    <Form >
        <Row>
            <Col lg="12">

                <FormGroup className="col-6">
                    <Input type="select" value=values.StateId name="StateId" onChange=this.handleChange(setFieldValue)>
                        <option value='' >Select State</option>
                        this.props.stateList && this.props.stateList.map((item, i) => (
                            <option key=i value=item.StateId>
                                item.StateName
                            </option>
                        ))
                    </Input>
                    this.validator.message('state', values.StateId, 'required')
                    <Label className="impo_label">Select State</Label>
                </FormGroup>

                <FormGroup className="col-6">
                    <Field className="form-control" name="GstNo" type="text" maxLength="15" />
                    <Label className="impo_label">GST No</Label>
                    this.validator.message('gst no', values.GstNo, 'required|min:15|max:15')
                </FormGroup>


            </Col>
        </Row>
    </Form>
)

现在,当我从下拉列表中更改状态时,将调用一个 API,该 API 将通过状态 ID 返回 gst no。我想用从道具中的 api 收到的值更新 gst no 字段。如果收到的 gst no 为空,那么我希望用户输入 gst no,但如果从 api 收到 gst no,我想用 props 中收到的值更新表单中的 gst no 字段并禁用表单输入。我无法更新 this.state.branchData 中的 gstno,因为这将使用 this.state.branchData 中的值重置表单值。

有人知道如何在 formik 中实现这一点吗?

【问题讨论】:

【参考方案1】:

当数据来自api。您可以像这样轻松更改字段的值:

setFieldValue('GstNo', valueFromApi)

【讨论】:

setFieldValue() 在 formik 表单之外无法访问。你有什么方法可以让我在 componenetWillRecieveProps() 的某个地方访问 formik 表单之外的 setFieldValue() 吗? 你可以调用formik里面的函数并调用它。示例:```
setGsNo(valueFromApi, setFieldValue)
``` 和外部formik: `` const setGsNo = (value, setFieldValue) => setFieldValue('GstNo', valueFromApi) ```
至少有codesandbox 对不起,我没有得到你的解决方案,你的代码框也没有工作。【参考方案2】:

我定义了一个用于维护 gstNo 的状态变量,它将根据从下拉列表中选择的状态 ID 从 API 中获取。像这样:

 this.state = 
   gstNo: null,
 ;

因此,当调用 API 并收到响应时,gstNo 属性将在 redux 存储中更新。

this.state.gstNo 将在 UNSAFE_componentWillReceiveProps() 中更新,当this.props.gstNo 更改时。如下:

if (this.props.gstNo !== nextprops.gstNo) 
  let gstNo;
  if (nextprops.gstNo) 
      gstNo = nextprops.gstNo;
   
  else 
      gstNo = null;
  

 this.setState(
   gstNo: gstNo,
  );

为了给formik赋值this.state.gstNo,我简单地写了这个:

<FormGroup className="col-6">
    <Field
        className="form-control"
        name="GstNo"
        disabled=this.state.gstNo
        type="text"
        maxLength="15"
        value=
            (values.GstNo = this
                .state.gstNo
                ? this.state.gstNo
                : values.GstNo)
        
    />
    <Label className="impo_label">
        GST No
    </Label>
</FormGroup>

因此,一旦this.state.gstNo 具有某些价值,它就会反映在 formik 表单的文本字段中,并且文本框将被禁用。

【讨论】:

【参考方案3】:

您可以启用 Formik 的 enableReinitialize 属性来更新字段。

<Formik
   enableReinitialize=true
   initialValues=...
>
....

【讨论】:

感谢您的解决方案,@Msilucifer。这真的节省了我的时间! :)【参考方案4】:

最好使用setFieldValue,当API获取一些值或者任何props/dependency值发生变化时,可以使用useEffect来处理, 例如: 我从父组件中获得了 setFieldValue 函数作为道具。

useEffect(() => 
    if (
        values.parentCategoryId &&
        !categories?.data?.find(category => category.id === values.categoryId)
            ?.hasFurnishingStatus
    ) 
        setFieldValue('furnishingStatus', '');
    
, [values?.categoryId]);

这里的furnishingStatus 是我要为其设置值的字段的名称。

<Field name="furnishingStatus" component=RadioGroup row>...</Field>

【讨论】:

以上是关于当redux store中的值发生变化时,如何更新formik中的特定表单字段?的主要内容,如果未能解决你的问题,请参考以下文章

Redux 与 Vuex 的区别总结

当 React JS 中的一项值使用地图函数中的状态发生变化时,如何动态更新购物车中的值?

当 uitableviewcell 中 uipickerview 的值发生变化时,我需要更新 viewcontroller 中的标签

redux reducer 不更新 store 中的状态

当提供者组件父状态发生变化时,为啥不能更新子组件中的值(带有反应上下文)?

当 ref 的值发生变化时,Vue 不会更新模板 Vue 3