简体   繁体   English

反应回调避免为孩子重新渲染

[英]React callback avoid re-render for child

I have trouble to avoid re-renders.我很难避免重新渲染。 Have a look in my simplified example: https://codesandbox.io/s/gracious-satoshi-b3p1u?file=/src/App.js Open the console.看看我的简化示例: https://codesandbox.io/s/gracious-satoshi-b3p1u?file=/src/App.js打开控制台。 I have expensive and heavy code in the child hook which filters a big array (not in this lightweight example).我在子钩子中有昂贵且繁重的代码,它过滤了一个大数组(不在这个轻量级示例中)。 Every time "child has been rendered" get's printed into the console, my browser laggs and crashes if i do it too often.每次“孩子已被渲染”都会打印到控制台中,如果我经常这样做,我的浏览器就会滞后并崩溃。

There is no state in Child . Child 中没有 state I just use it to add a certain text piece (user can select from a big list of emojis and special chars) if i click to the textarea which needs a callback to communicate.如果我单击需要回调进行通信的文本区域,我只是使用它来添加某个文本片段(用户可以从大量表情符号和特殊字符中获取 select)。 I tried React.useMemo() and useMemo() but neither worked.我尝试React.useMemo()useMemo()但都没有奏效。

You should use useCallback to memoize functions/event handlers and avoid creating them every time, and also for child components you should use memo to rerender only if props have changed您应该使用useCallback来记忆函数/事件处理程序并避免每次都创建它们,并且对于子组件,您应该仅在道具发生更改时才使用memo重新呈现

App.js应用程序.js

import React, { useCallback, useState } from "react";
import Child from "./Child";

export default function App() {
  const [data, setData] = useState({ title: "default title", test: null });
  const cb1 = useCallback(
    (x) => setData({ ...data, title: x.target.value }),
    []
  );
  const cb2 = useCallback((x) => setData({ ...data, test: x }), []);

  return (
    <div>
      <p>Title: {data.title}</p>
      <p>Test: {data.test}</p>

      <input onChange={cb1} />
      <Child clickCallback={cb2} />
    </div>
  );
}

Child.js Child.js

import { memo } from "react";

export default memo(function Child(props) {
  return (
    <>
      {console.log("child has been rendered")}
      <button onClick={() => props.clickCallback("test")}>test</button>
      <button onClick={() => props.clickCallback("test2")}>test2</button>
      <button onClick={() => props.clickCallback("test3")}>test3</button>
      <button onClick={() => props.clickCallback("test4")}>test4</button>
    </>
  );
});

check a working example here https://codesandbox.io/s/vibrant-curran-tv502在这里查看一个工作示例https://codesandbox.io/s/vibrant-curran-tv502

Try this.尝试这个。 Add useMemo dependancies as needed,根据需要添加 useMemo 依赖项,

 export default function App() { const [data, setData] = useState({ title: "default title", test: null }); const childs = useMemo(() => { return ( <Child clickCallback={(x) => setData({...data, test: x })} /> ) }, []); return ( <div> <p>Title: {data.title}</p> <p>Test: {data.test}</p> <input onChange={(x) => setData({...data, title: x.target.value })} /> {childs} </div> ); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM