Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Suppose I have these React components:

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

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

And the nested component, wrapped in memo:

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

Function passed in foo is always recreated in Compo1 and also Compo2, correct?

If so, since foo receives a new function every time, does it mean memo will be useless, thus Nested will always be re-rendered?

like image 608
rodrigocfd Avatar asked Jan 25 '19 15:01

rodrigocfd


People also ask

Do components re-render when props change?

In order for props to change, they need to be updated by the parent component. This means the parent would have to re-render, which will trigger re-render of the child component regardless of its props.

Can you pass a component as a prop React?

You can pass a component as props in React by using the built-in children prop. All elements you pass between the opening and closing tags of a component get assigned to the children prop.

How do you memoize a component in React?

React also gives us a memo() hook to apply memoization for functional components. If we need a function component that gives the same result for the same props and we don't want to re-render it, we can use memoization to skip the re-render of the component by storing and reusing the last rendered result.

How do we prevent unnecessary re renders even when props remain the same?

1. Memoization using useMemo() and UseCallback() Hooks. Memoization enables your code to re-render components only if there's a change in the props. With this technique, developers can avoid unnecessary renderings and reduce the computational load in applications.


1 Answers

You can use new hooks Api(React >= 16.8) to avoid recreating callback func.

Just using useCallback hook for this.

For e.g

Parent component

import React, { useCallback} from 'react';

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

  const memoizedCallback = useCallback(theFoo , []);

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

useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed (which passed in the second argument) In this case we pass empty array as dependencies and therefore the function will be created only once.

And nested component:

import React, { memo } from 'react';

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

export default memo(Nested);

For more info - https://reactjs.org/docs/hooks-reference.html#usecallback

like image 133
Artur Khrabrov Avatar answered Sep 17 '22 22:09

Artur Khrabrov