是否因为函数而导致子级重新渲染



我在导航这些概念时遇到了问题,因为我从父级传递了一个函数,所以子级一直在重新渲染。这个父函数引用了一个编辑器的值draftjs。

function Parent() {
const [doSomethingValue, setDoSomethingValue] = React.useState("");
const [editorState, setEditorState] = React.useState(
EditorState.createEmpty()
);
const editorRef = useRef<HTMLInputElement>(null);
const doSomething = () => {
// get draftjs editor current value and make a fetch call
let userResponse = editorState.getCurrentContent().getPlainText("u0001");
// do something with userResponse
setDoSomethingValue(someValue);
}
return (
<React.Fragment>
<Child doSomething={doSomething} />
<Editor
ref={editorRef}
editorState={editorState}
onChange={setEditorState}
placeholder="Start writing..." />
<AnotherChild doSomethingValue={doSomethingValue}
<React.Fragment>
}
}

"我的孩子"组件只是一个按钮,它调用家长的doSomething,仅此而已。

doSomething做它的事情,然后对状态进行更改,然后将其传递给AnotherChild。

我的问题是,每当editorState更新时(也就是每次在编辑器中键入时(,我的Child组件都会重新渲染。这不是没有必要吗?如果是这样,我该如何避免这种情况?

如果我给我的Child组件传递一个字符串并利用React.Memo,它不会重新呈现,除非字符串发生变化。

那么,将函数传递给孩子会遗漏什么呢我的孩子每次都应该重新渲染吗

React致力于引用更改检测,以重新渲染组件。

Child.js:将其包裹在React.memo下,使其成为纯组件。

const Child = ({doSomething}) => <button onClick={doSomething}>Child Button Name</button>;
export default React.memo(Child);

Parent.js -> doSomething:在每次(重新(渲染时,也会重新创建回调。使用useCallback,这样就不会在每次渲染时重新创建函数。

const doSomething = React.useCallback(() => {
let userResponse = editorState.getCurrentContent().getPlainText("u0001");
setDoSomethingValue(someValue);
}, [editorState]);

旁注

在更广泛的范围内,memo是HOC,并使组件成为纯组件。useMemo是缓存函数输出的东西。而useCallback缓存函数的实例。

希望能有所帮助。

如果不希望每次重新渲染父级时都重新渲染组件,则应查看useMemo

这个函数只会在它的第二个参数发生变化时(这里,它唯一依赖的是doSomething()(重新计算它的值(在您的情况下,是您的组件(。

function Parent() {
const [editorState, setEditorState] = React.useState(
EditorState.createEmpty()
);
const editorRef = useRef<HTMLInputElement>(null);
const doSomething = () => {
// get draftjs editor current value and make a fetch call
let userResponse = editorState.getCurrentContent().getPlainText("u0001");
// do something with userResponse
}
const childComp = useMemo(() => <Child doSomething={doSomething} />, [doSomething])
return (
<React.Fragment>
{childComp}
<Editor
ref={editorRef}
editorState={editorState}
onChange={setEditorState}
placeholder="Start writing..." />
<React.Fragment>
}
}

如果doSomething未更改,则组件不会重新渲染。

如果函数正在进行繁重的计算,您可能还想对其使用useCallback,以避免每次组件渲染时都对其进行重新编译:https://reactjs.org/docs/hooks-reference.html#usecallback

查看PureComponentuseMemoshouldComponentUpdate

我还想补充一点,不是传递函数来渲染顶级组件,而是传递值,然后在组件树中向下定义函数。

如果你想避免不必要的重新渲染,你可以使用React.memo和钩子useCallback。看看下面的沙盒。button1总是被重新呈现,因为它接受了一个没有用useCallback记忆的回调,而button2只是第一次呈现,即使父级的状态已经改变(查看控制台以检查重新呈现(。您必须在负责呈现按钮的子组件中使用React.memo。

我希望它能有所帮助。

最新更新