6

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>
     )
  }
}
arnaudambro
  • 2,403
  • 3
  • 25
  • 51
  • You are overcomplicating things. Do you have a performance problem? – Jonas Wilms Feb 18 '19 at 15:17
  • 1
    I actually do : my app is pretty big (much bigger than that), using redux, and one of my deep nested component uses draft-js. I would like to store the EditorState in my redux store for conveniency, but I can't do it now because of performance and too many re-rendering issues making the text editor lagging. I would like to give a shot to this optimization, because I already have done many more (recompose, reselect, etc.) – arnaudambro Feb 18 '19 at 15:27

3 Answers3

4

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.

Eddie Cooro
  • 1,676
  • 14
  • 18
1

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>
)};
Rin3
  • 119
  • 1
  • 10
  • 4
    Is this creating a new `style` variable each time though? The previous `style` and current `style` object would have different addresses, right? – 425nesp Feb 07 '20 at 01:56
1

An object can be memoized with useMemo hook:

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

Since useMemo is intended for expensive calculations and has its own overhead, this may be considered premature optimization for div case.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • 1
    thanks for your reply, what do you suggest for class components ? I edited my post with a proposal, what do you think about it ? – arnaudambro Feb 18 '19 at 17:22
  • 1
    `useMemo` is specific to functional components. You can use general-purpose memoizer like Lodash. As I mentioned, this optimization doesn't make much sense for
    . As for class components with custom props, a better thing is to make them responsible for rerender decisions instead and use shouldComponentUpdate.
    – Estus Flask Feb 18 '19 at 17:41
  • 1
    @estus Can you please tell what expensive calculations are needed for it? – Eddie Cooro Feb 18 '19 at 20:58
  • @EddieCooro Some function that takes considerable amount of CPU or RAM, e.g. complex object object. – Estus Flask Feb 18 '19 at 21:18