【问题标题】:React not triggering re-render with useState hook使用 useState 钩子反应不触发重新渲染
【发布时间】:2019-08-21 06:51:50
【问题描述】:

我有一个由类别 > 字段 > 然后每个字段有多个有效行构成的表单组件。我使用 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() 但没有重新使成为?

更新:我已经解决了这个问题(虽然我承认不完全理解为什么我的原件不起作用),请参阅下面的答案

【问题讨论】:

  • 你的 cloneAndUpdate() 方法是什么样的?
  • 您能否针对您的问题发布一个代码框!
  • @christopher-ngo cloneAndUpdate() 是来自 immutability-helper 库github.com/kolodny/immutability-helper的更新方法

标签: javascript reactjs state react-hooks


【解决方案1】:

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

【讨论】:

  • 我认为可能是这种情况,所以我直接从formValuesById 输出了一些信息,它似乎没有帮助(我已经用我使用的调试更新了我的 OP)但它仍然没有'不触发重新渲染。我现在想知道我的“克隆”对象是否触发了差异
  • 您的状态似乎很复杂。你为什么不试试useReducer 而不是useStatereactjs.org/docs/hooks-reference.html#usereducer
【解决方案2】:

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

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

我认为该库实际上并没有进行深度复制,而是重新使用了结构中未更改的部分,因此我怀疑尝试手动更新它实际上是在更新对新的反应并因此做出反应的原始参考设置状态时识别没有区别。使用库中记录的正确$push 语法修复了它。

【讨论】:

    猜你喜欢
    • 2020-10-29
    • 2020-01-26
    • 2021-11-10
    • 2022-01-04
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 2020-08-06
    • 2020-08-03
    相关资源
    最近更新 更多