React没有使用useState钩子触发重新渲染

时间:2019-08-21 06:51:50

标签: javascript reactjs state react-hooks

我有一个由类别>字段构成的表单组件,然后每个字段有多个有效性行。我使用useState()跟踪表单值状态(每个字段ID的有效性行)。子组件中有一个添加按钮,可触发addValidityRowCallback添加另一个有效性行。

我正在尝试更新状态并触发重新渲染,但它似乎不起作用。

import React, {useState} from 'react'
import CollapsibleFieldset from "../../fieldsets/CollapsibleFieldset";
import PersonInfoTypeFormRow from "./PersonInfoTypeFormRow";
import cloneAndUpdate from 'immutability-helper';


export default function PersonInfoForm({personInfoFormDataJson, webServiceAddress}) {

    let [targetPersonId, formCategories, defaultFormValuesIndexedById] = parsePersonInfoJsonString(personInfoFormDataJson);

    const [ formValuesById, setFormValues ] = useState(defaultFormValuesIndexedById);

    const addValidityRowCallback = (personInfoTypeId) => {
        let newEmptyRow = {id:12345, value:["NEW"], valueTitle:"","validityStartDate":"",createdDateTime:"",createdByPersonId:1212};
        let newFormValuesState = cloneAndUpdate(formValuesById, {});
        newFormValuesState[personInfoTypeId].push(newEmptyRow);
        setFormValues(newFormValuesState);
    };

    return <form className="personInfoForm pure-form">
            {formCategories.map((category) => {
                return <CollapsibleFieldset key={category.id || category.title} legend={category.title}>
                    {category.personInfoTypes.map((personInfoType) => {
                        return <PersonInfoTypeFormRow {...personInfoType} key={personInfoType.id} addValidityRowCallback={addValidityRowCallback} values={formValuesById[personInfoType.id]}/>
                    })}
                </CollapsibleFieldset>
            })
            {/* DEBUG........ */}
            {Object.keys(formValuesById).map(fieldId => {
                return formValuesById[parseInt(fieldId)].map(validityRow => {
                    return <h3 key={validityRow.id}>{validityRow.id}</h3>
                })
            })}
        }
    </form>;
}

我可以在调试器中看到正确调用了addValidityRowCallback函数,克隆了现有状态,在结构中的正确位置添加了新行,然后将新状态传递回setFormValues()但没有重新渲染?

更新:我已经解决了这个问题(尽管不能完全理解为什么我的原版不起作用),请在下面查看我的答案

2 个答案:

答案 0 :(得分:0)

问题是您渲染formCategories却将formValuesById设置为状态。因此,如果在状态上保存formValuesById,则需要保存formCategories

答案 1 :(得分:0)

好的,我通过cloneAndUpdateHooks API Reference)方法而不是之后的方法更新对象来解决了此问题

assign[personInfoTypeId] = {$push:[newEmptyRow]};
let newPersonInfoTypeFieldsState = cloneAndUpdate(formValuesById,assign);
setFormValues(newFormValuesState);

我认为该库实际上不是在进行深层复制,而是重新使用结构的未更改部分,因此我怀疑稍后尝试手动更新实际上是在更新原始引用,从而做出新反应。设置状态时没有发现差异。使用库中记录的正确$push语法对其进行了修复。