Re-rendering 仅更新 React 表单上的元素

Re-rendering only updated elements on react form

我想实现一个动态构建的表单,其中包含可扩展的受控组件。我遇到的问题是更新状态导致整个表单 re-render(或昂贵的东西?)导致史诗类型滞后。

// Generate some example fields
let defaultFields = {};
for(let n=0; n<1000; n++){
    defaultFields[n.toString()] = {'id':n.toString(), 'value':'','label':'Field '+n}
}
const [valuesById, setValuesById] = useState(defaultFields);

const updateValueCallback = React.useCallback((e)=>{
    e.preventDefault();
    e.persist();
    setValuesById(prevValuesById => {
        let fieldId = e.target.id;
        return {...prevValuesById,
            [fieldId]:{
                'id':fieldId,
                'value':e.target.value,
                'label':'Field '+fieldId
        }};
    });
});
return <div>
    { Object.entries(valuesById).map(([id,formField]) => {
        return <p key={formField.id}>
            <label>{formField.label}
                <SingleLineStringInput isRequired={false} value={formField.value} onChangeCallback={updateValueCallback} id={formField.id} name={'name_'+formField.id} />
            </label>
        </p>
    })
    }
</div>;

如果 999 个字段的道具都没有改变,那为什么 re-render?或者这里实际发生了什么(这些字段实际上并没有在调试工具中闪烁,但 parent 会)?我真的需要帮助来更好地理解这一点,并且需要一个与我所做的没有太大不同的修复,因为我们已经在这个基本结构之上构建了大量逻辑,并且现在才意识到它没有扩展。

单线输入:

const SingleLineStringInput = React.memo(({name, id, value, onChangeCallback}) => {
    console.log("UPDATING "+id);
    return <input className={'input ' + inputClasses.join(' ')} name={name} id={id} type="text"
                  value={(value === null) ? '' : value}
                  onChange={onChangeCallback} />
});

好的,我会尽力提供帮助,你使用 memo 和 useCallback 做得很好,但你没有将 依赖数组传递给 useCallback,因为你的回调对于每个渲染,你可以传递一个空数组给它,所以它在每个渲染上都是相同的函数, 你可以这样做

const updateValueCallback = React.useCallback((e)=>{
e.preventDefault();
e.persist();
setValuesById(prevValuesById => {
    let fieldId = e.target.id;
    return {...prevValuesById,
        [fieldId]:{
            'id':fieldId,
            'value':e.target.value,
            'label':'Field '+fieldId
    }};
});
}, []); // dependencies array

现在,如果您更改字段值,将重新呈现该字段值

Sandbox 向您展示它是如何完成的

希望对您有所帮助