Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid rerender in React caused by objects literal : how to do with variables in the object?

I read in this article React is Slow, React is Fast: Optimizing React Apps in Practice that :

In fact, each time you pass an object literal as prop to a child component, you break purity.

Alright, I got it. So the best to avoid that is to create a variable with the object, and insert this variable in the prop, like that :

import React from 'react';

const style = { marginTop: 10 };
const AnyComponent = (props) => (
    <div style={style}>
        ...
    </div>
)

But what if the style prop depend on a received prop ? Where should be the object ? So for instance, I have this component:

import React from 'react';

const AnyComponent = (props) => (
    <div style={{ marginTop: props.marginTop }}>
        ...
    </div>
)

Is it a good practice to do:

import React from 'react';

const style = (marginTop) => ({ marginTop })
const AnyComponent = (props) => (
    <div style={style(props.marginTop)}>
        ...
    </div>
)

[EDIT] I forgot to say that most of my components have state, so in that case, is it a good idea to do :

import React from 'react';

class App extends React.Component {

  style = () => ({
    marginTop: this.props.marginTop
  })

  render() {
    return(
      <div style={this.style()}>

      </div>
     )
  }
}
like image 380
arnaudambro Avatar asked Feb 18 '19 14:02

arnaudambro


People also ask

How do you prevent re-rendering of components that have not changed?

To prevent excessive re-rendering, move the expensive component to a parent component, where it will render less often, and then pass it down as a prop. If this is not enough, inject React. memo into the code for better performance.

How do you prevent a child component from re-rendering in React?

React does not care whether “props changed” - it will render child components unconditionally just because the parent rendered! If you don't want a component to re-render when its parent renders, wrap it with memo. After that, the component indeed will only re-render when its props change.

Does changing props cause re-render?

⛔️ Re-renders reason: props changes (the big myth) 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.


2 Answers

Previously you couldn't do this in functional components (although you could use memoization) But now by the favor of React hooks, you can do something like this:

const AnyComponent = (props) => {
    const style = useMemo(() => ({ marginTop: props.marginTop }), [props.marginTop]);
    <div style={style}>
        ...
    </div>
}

And no, you can't use this one:

import React from 'react';

const style = (marginTop) => ({ marginTop })
const AnyComponent = (props) => (
    <div style={style(props.marginTop)}>
        ...
    </div>
)

Because it also creates a new object on every re-render of AnyComponent by calling the style function each time.

like image 141
Eddie Cooro Avatar answered Oct 19 '22 14:10

Eddie Cooro


You could create your variable in your component, as follow:

import React from 'react';

const AnyComponent = (props) => {
 // if props.marginTop is an object
 const style = props.marginTop;

 return (
    <div style={style}>
        ...
    </div>
)};
like image 2
Rin3 Avatar answered Oct 19 '22 14:10

Rin3