使用记忆时反应子组件不同步

React child components out of sync when using memoization

我有一个由几个“更大”子组件组成的组件,其中一个是自定义表单 CustomForm,它又由几个自定义输入字段组成 CustomField.

为了提高页面的性能,我想记住该表单,以便它仅在至少 data 值之一发生变化时才重新呈现(data 是主要组件的状态).
同时,我还想记住各个输入字段,因此它们只会在各自的值发生变化时重新呈现。

以下是一个最小的工作示例 - 我省略了应用程序的其他部分并简化了表单和输入字段:

import React, { useState} from 'react';


function CustomFieldComponent(props) {
    const { labelText, data, handleChange } = props;

    console.log("renders", labelText);

    return (
        <input id={labelText} key={labelText} value={data[labelText]} onChange={handleChange}/>
      )
}

function compareTextfield(prevProps, nextProps) {
    return prevProps.data[prevProps.labelText] === nextProps.data[nextProps.labelText];
}

const CustomField = React.memo(CustomFieldComponent, compareTextfield);


function CustomFormComponent(props) {
    const { data, handleChange } = props;

    return (
        <div>
            <CustomField labelText="field1" data={data} handleChange={handleChange}/>
            <CustomField labelText="field2" data={data} handleChange={handleChange}/>
            <CustomField labelText="field3" data={data} handleChange={handleChange}/>
        </div>
    )
}

function compareForm(prevProps, nextProps) {
    return prevProps.data === nextProps.data;
}

const CustomForm = React.memo(CustomFormComponent, compareForm);


export default function Test(props) {
    const [data, setData] = useState({"field1": "value1", "field2": "value2", "field3": "value3"});


    const handleChange = (e) => {
        var local_data = {...data};
        local_data[e.target.id] = e.target.value;
        setData(local_data);
    }


    // other parts of the component

    return (
        <div>
            <CustomForm data={data} handleChange={handleChange}/>
            <br/>
            This is data:
            {
                Object.keys(data).map((key, index) => ( 
                    <div key={index}>{data[key]}</div> 
                ))
            }
        </div>
    )
}

关于不同组件的不必要的重新呈现,此代码按预期工作,但是各个输入字段不同步。例如,当我在 field1 中输入一些文本,然后在 field2 中输入一些文本时,field1 的先前输入被重置(即,先前在 data 中更改的值在随后的 data 中被覆盖输入)。

似乎问题出在 CustomFieldComponent 的记忆(使用 CustomField),因为如果我在 [=22= 中使用非记忆的 CustomFieldComponent 本身], 一切都按预期工作,并且用户输入正确地保存在不同的字段中。

我的问题是,如何在保持各个输入字段与 data 同步的同时实现所需的记忆?

已找到修复方法。问题是主要组件中的 handleChange 函数。
必须是:

const handleChange = (e) => {
    setData(prev => ({...prev, [e.target.id]: e.target.value}));
}