Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何在不触发React中的子级重新呈现的情况下在父级中设置状态?_Reactjs - Fatal编程技术网

Reactjs 如何在不触发React中的子级重新呈现的情况下在父级中设置状态?

Reactjs 如何在不触发React中的子级重新呈现的情况下在父级中设置状态?,reactjs,Reactjs,我有一个React web应用程序,可以有效地回答大量问题。这些问题需要根据各自的状态值(即:必须是数字字段中的数字)以及彼此的值进行验证/布局。一些更复杂的“验证”示例: 在允许“保存”按钮之前,问题A、B和C可能需要具有非空值 问题B的允许值范围可能取决于问题A的值 只有当问题A设置为“真”时,问题C才会显示 你可以想象许多其他的互动。该应用程序有数百个问题——因此,我在JSON对象中有它们的配置,如下所示: { id: 'version', required: true, label:

我有一个React web应用程序,可以有效地回答大量问题。这些问题需要根据各自的状态值(即:必须是数字字段中的数字)以及彼此的值进行验证/布局。一些更复杂的“验证”示例:

  • 在允许“保存”按钮之前,问题A、B和C可能需要具有非空值
  • 问题B的允许值范围可能取决于问题A的值
  • 只有当问题A设置为“真”时,问题C才会显示
你可以想象许多其他的互动。该应用程序有数百个问题——因此,我在JSON对象中有它们的配置,如下所示:

{ id: 'version', required: true, label: 'Software Version', xs: 3 },
{
    id: 'licenseType', label: 'License Type', xs: 2,
    select: {
        [DICTIONARY.FREEWARE]: DICTIONARY.FREEWARE,
        [DICTIONARY.CENTER_LICENSE]: DICTIONARY.CENTER_LICENSE,
        [DICTIONARY.ENTERPRISE_LICENSE]: DICTIONARY.ENTERPRISE_LICENSE
    }
},
... etc.
function Question(props) {
    const { qConfig, valueChangedListener, defaultValue } = props;
    const [value, setValue] = useState(props);

    useEffect(() => {
        if (qConfig.value && typeof defaultValue !== 'undefined') {
            setValue(qConfig.value);
        }
    }, [qConfig.value])


    const handleValueChange = (evt, id) => {
        setValue(evt.target.value);
        valueChangedListener(evt.target.value, id)
    }

    return <div style={{ maxWidth: '100%' }}>
        <TextField
            // various other params unrelated...
            value={value ? value : ''}
            onChange={(evt) => handleValueChange(evt, qConfig.id)}
        >
        // code to handle 'select' questions.
        </TextField>
    </div>
}
然后,我将使用
FormPage
组件中的一个映射,将这个对象转换为实际问题,该组件是所有问题的父级。考虑到需要将这些交互存储在最接近的公共父对象中,我将所有
问题
值存储在
formData
状态变量对象中,
FormPage
如下所示:

function FormPage(props) {
    const [formData, setFormData] = useState(BLANK_REQUEST.asSubmitted);

    const handleValueChange = (evt, id) => {
        setFormData({ ...formData, [id]: evt.target.value})
    }

    return <div>
        {QUESTIONS_CONFIG.map(qConfig => <Question  qConfig={qConfig} value={formData[qConfig.id]} handleValueChange={handleValueChange}/>)}
        // other stuff too
    </div>
}
值得注意的是,现在,当它的值更改时,它只存储它自己的值,让
FormPage
知道它的值已更新,以便
FormPage
可以执行一些多问题验证

为了完成此操作,我在
FormPage
上添加了一个回调函数:

const processValueChange = (value, id) => {
    setFormData({ ...formData, [id]: value })
};
然后保留我的useEffect,它基于formData进行交叉问题验证:

useEffect(() => { // validation is actually bigger than this, but this is a good example
        let missingArr = requiredFields.filter(requiredID => !formData[requiredID]);
        setDisabledReason(missingArr.length ? "Required fields (" + missingArr.join(", ") + ") must be filled out" : '');
}, [formData, requiredFields]);
FormPage
返回的内容对此有一个微小的更改:

return <div>
    {questionConfiguration.map(qConfig => 
        <Question
            qConfig={qConfig}
            valueChangedListener={processValueChange}
        />
    </ div>
    )
}
但那没用

我的猜测是,即使
formData
FormPage
上的状态对象)没有在返回中使用。。。它的修改仍然会每次触发完全重新渲染

但是我需要存储孩子们的价值,这样我就可以用这些价值做一些事情

。。。但是如果我将子级的值存储在父级状态中,它会重新呈现所有内容,并且速度慢得令人无法接受

我不知道怎么解决这个问题?帮忙

功能组件如何存储其子组件的所有值(用于验证、布局等)。。。在每次修改所述数据时不触发重新渲染?(我只希望在验证/布局函数发现需要更改的内容时重新渲染)

编辑: 最小沙箱:


我在问题组件中有一个console.log,这样我们可以看到它们何时呈现。

很可能是
usemo
useCallback
的组合。很难说没有一个我将如何快速构建一个代码沙盒。。。
const processValueChange = React.useCallback((value, id) => {
        setFormData({ ...formData, [id]: value })
    }
},[]);