好的。这是我的情况。我有一个叫做TheForm
的大组件。在TheForm
中,有以下孩子:TextEditor
,TagInput
,TipCard
- 这给出了如何写一个好的形式和Preview
的建议:
const TheForm = () => {
const [parag1, writeParag1] = useState("");
const [parag2, writeParag2] = useState("");
const [tags, updateTags] = useState([]);
return (
<div>
<TipCard>Some suggestion here...</TipCard>
Paragraph One: <TextEditor onInput={writeParag1}/>
Paragraph One: <TextEditor onInput={writeParag2}/>
Add tags: <TagInput onInput={updateTags}/>
Preview Mode: <Preview />
<button>Submit</button>
<button>Reset</button>
</div>
);
}
该TextEditor
包含一个<textarea>
,一些用于格式化文本的按钮,每次<textarea>
的值发生变化时,TheForm
中的正确状态都会更新。TagInput
也一样。
Preview
将获取状态值并在预览模式下呈现它们(就像堆栈溢出提出问题一样(。
这里的问题是,当其中一个状态被更新时,它会导致所有子级重新渲染,即使他们没有使用该状态,甚至我都使用了组件的React.memo
。
我知道当状态发生变化时,它会重新渲染组件,因此组件的子组件也会重新渲染。
那么我怎样才能避免呢?我知道我可以将状态下移到子级,但是如果我这样做,Preview
就无法访问这些值。Redux 可以解决这个问题,但在这里使用 Redux 是不是太多了,我的意思是这些状态不与其他组件共享,所以使用 Redux 太多了?
这就是 React 的工作方式 - 每次状态更改时它都会运行渲染函数,并且它会导致所有子级也重新渲染,无论它们是否依赖于更改的状态。
如果你想避免重新渲染一个组件,你可以让它纯净,例如用React.memo
包装它。因此,您必须包装每个子项以防止其重新渲染。
纯组件浅层比较props
确定跳过从父级请求的重新渲染是否安全。这意味着,您不仅要包装子项以memo
,还要确保传递给它们的道具在每次渲染时都是持久的。 通常这意味着您应该像onInput={el => updateTitle(el.target.value)}
useMemo
或useCallback
并避免、展平或记忆像previewMode={{ title, description, codeBlock, tagList }}
这样的对象,否则它们每次都会被重新创建,并且会使浅层比较优化无效