繁体   English   中英

响应备忘录组件并在将函数作为道具传递时重新渲染

[英]React memo components and re-render when passing function as props

假设我有这些React组件:

const Compo1 = ({theName}) => {
  return (
    <Nested foo={() => console.log('Dr. ' + theName)}/>
  );
};

const Compo2 = ({theName}) => {
  function theFoo() {
    console.log('Dr. ' + theName);
  }
  return (
    <Nested foo={theFoo}/>
  );
};

和嵌套组件,包含在memo

const Nested = React.memo(({foo}) => {
  return (
    <Button onClick={foo}>Click me</Button>
  );
});

foo传递的函数总是Compo1Compo2 重新创建Compo1吗?

如果是这样,因为foo每次都会收到一个新函数,它是否意味着memo将无用,因此Nested将永远重新渲染?

您可以使用新的钩子Api(React> = 16.8)来避免重新创建回调函数。

只需使用useCallback钩子。

例如

父组件

import React, { useCallback} from 'react';

const ParentComponent = ({theName}) => {
  const theFoo = () => {
    console.log('Dr. ' + theName);
  }

  const memoizedCallback = useCallback(theFoo , []);

  return (
     <Nested foo={memoizedCallback}/>
   );
};

useCallback将返回一个回调的memoized版本,该版本只在其中一个依赖项发生更改时才会更改(在第二个参数中传递)。在这种情况下,我们将空数组作为依赖项传递,因此该函数只会创建一次。

和嵌套组件:

import React, { memo } from 'react';

const Nested = ({foo}) => (
  <Button onClick={foo}>Click me</Button>
);

export default memo(Nested);

有关详细信息, 请访问https://reactjs.org/docs/hooks-reference.html#usecallback

memo功能将浅显比较每个不同的道具,包括功能。 但是,通过在每个渲染中重新定义组件内部的函数,每次都会创建一个不同的引用,从而触发重新渲染。

虽然,正如您在Comp3看到的那样,您仍然可以使用备忘录并通过声明外部函数来避免重新渲染:

 class App extends React.Component { constructor(props) { super(props) this.state = { } } componentDidMount = () => { setInterval(() => { this.setState({ e: true }) }, 2000) } render() { return ( <div> <Compo1 /> <Compo2 /> <Compo3 /> </div> ) } } const Compo1 = () => <Nested foo={() => console.log('Comp1 rendering')} /> const Compo2 = () => { function theFoo() { console.log('Comp2 rendering'); } return <Nested foo={theFoo} /> }; const foo3 = function (text) { console.log('Comp3 rendering ' + text) } const Compo3 = () => <Nested foo={foo3} /> const Nested = React.memo(({ foo }) => { foo('a param') return <div /> }) ReactDOM.render(<App />, document.getElementById('root')) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id='root'> 

我找到的最好的方法是使用useRef 具体来说,我将此结构与Formik一起使用,以防止重新呈现一长串输入值。

const MyMemoizedGroupList = React.memo(
  ({
    groups,
    arrayHelpersRef,
  }) => {
    // [..] stuff
  }
}

function MainComponent() {
  const groupsArrayHelpersRef = React.useRef();

  return (
    <Formik 
      // [..] stuff
      render={({ values }) => (
        <Form>
          <FieldArray
            name="groups"
            render={arrayHelpers => {
              groupsArrayHelpersRef.current = arrayHelpers;
            }}
          />
          <MyMemoizedGroupList 
            groups={values.groups} 
            arrayHelpersRef={groupsArrayHelpersRef} 
          /> 
          {/* [..] stuff */}
        </Form>
      )} 
    />
  );
}

暂无
暂无

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

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