React: Best way to handle the re-rendering in reusable components

Created on 28 May 2019  ·  3Comments  ·  Source: facebook/react

I have asked this question on stackoverflow (here). Unfortunately I did not get any answers.

Basically, I would like to create my own reusable components that can be used in other projects (as npm package).

Let assume that the reusable components are structured in this way:

├───card.jsx
├───card-board.jsx
├───card-body.jsx
├───sliding.jsx
├───sliding-board.jsx
├───sliding-body.jsx
├───img.jsx
├───remove.jsx
├───title.jsx
└───index.jsx

Usage Example:

this.state.Cards.map(card => {
  return (
    <Card key={card.id}>
      <Remove onRemove={() => this.handleCardRemove(card.id)} />
      <Img />
      <CardBody>
        <Title>{card.title}</Title>
        <p>{card.body}</p>
      </CardBody>
    </Card>
  );
});

It worked great until the number of cards are overpopulated. All the update and delete function became really slow due to the waste re-rendering on the same static content.

And of course this can be optimized by checking the previous and the new props in the Card component as below:

import React from "react";

import { CardContainer } from "./card.style";
import { deepCompare } from "../../utils/";

const Card = ({ children }) => {
  return <CardContainer>{children}</CardContainer>;
};

// if return true - Card component won't re-render
const arePropsEqual = (preProps, newProps) => {
  return deepCompare(preProps, newProps); // <- function that compare the nested props.
};

export default React.memo(Card, arePropsEqual);

As you can see. I'm using React.memo to control the re-rendering and I also implemented the deepCompare function that will return true if both input props are the same.

So, I would like to know what is the best way to handle this kind of problem in the large scale where there are a lot of components (probably nested).

And, Should the above solution(React.memo) be applied for each individual ui component that I created?. Because some of the ui element can be used individually without depending on some kind of container eg: Img, Remove and Title component.

Most helpful comment

@Cwanyo what you want is something like react-virtualized or react-window. The problem you are seeing is specific to large lists, and the optimization to handle it is best done at the List level not, individual components. Arbitrarily wrapping all components in React.memo could actually make apps slower, if the amount of work to compare (especially deep compares) is more significant than re-rendering. That should be measured in your app, and is likely to be very different app to app. This is why most ui libraries like react bootstrap and material ui _don't_ use React.memo for their components. Instead the consumer should first measure, and then use as needed on bottlenecks, but not as a general rule.

So to answer your question:

what is the best way to avoid the waste re-rendering on the component that didn't have any changes in props.

That's probably the wrong question to ask. first ask if the re-render actually _matters_ in terms of performance. Preventing re-renders is not an automatic benefit. In your case the problem is best solved not by preventing rerenders but by rendering less things at the same time.

All 3 comments

I commented in the Stackoverflow.
I believe it is due to many rendered components that slows the browser down.

@kunukn Thank you for your attention. Actually I do understand that it is not a good practice to render a ton of elements in the single page.

However, the main objective that I want is that I would like to create the reusable components that can handle the re-rendering automatically. So the user don't have to write the extra code for detecting the changes of the content in the particular used component.

And of course there is something like the PureComponent that can be used in this case. However, it is not working perfectly if the component contains children in side the props. Because what It did is just the shallow comparison between the previous and new props.

Basically, I want to know what is the best way to avoid the waste re-rendering on the component that didn't have any changes in props. So I can apply the solution to other reusable components that I created.

@Cwanyo what you want is something like react-virtualized or react-window. The problem you are seeing is specific to large lists, and the optimization to handle it is best done at the List level not, individual components. Arbitrarily wrapping all components in React.memo could actually make apps slower, if the amount of work to compare (especially deep compares) is more significant than re-rendering. That should be measured in your app, and is likely to be very different app to app. This is why most ui libraries like react bootstrap and material ui _don't_ use React.memo for their components. Instead the consumer should first measure, and then use as needed on bottlenecks, but not as a general rule.

So to answer your question:

what is the best way to avoid the waste re-rendering on the component that didn't have any changes in props.

That's probably the wrong question to ask. first ask if the re-render actually _matters_ in terms of performance. Preventing re-renders is not an automatic benefit. In your case the problem is best solved not by preventing rerenders but by rendering less things at the same time.

Was this page helpful?
0 / 5 - 0 ratings