Performance tips to have in mind while writing React components
As I was fine-tuning the React components I am working on, I tested and played with different ways I could re-write the code. I am compiling all the tips I learned, the performance tips to have in mind while I am writing the code.
- Pay attention what you are sending as props into the component. React components trigger a re-render when
props
orstate
changes. Send props that change less often. For example, see the code below:
The index
and selectedNoteIndex
are passed to the component as props
, this way changing selectedNoteIndex
or anything that changes the index
, changes the props
and it triggers a re-render for all the components created by map
! Another way to write the code above would be:
Now only a Boolean (selected
) is sent to the component as props
and the comparison is performd upper in the hierarchy.
- Break large components into smaller ones. DRY. Big components are hard to maintain and fine-tune. Big components are all rendered at once. Turn the parts inside
map
s into their own components. For example, even if you have to passindex
into the component in the example above, break the component into two parts, one that needsindex
and one that does not:
This way at least a part of the DOM tree is not re-rendered.
- Have small
state
s or none at all. Side effects and states are one of the main sources of bugs. Keepingstate
in sync with theprops
needs implementing the React life-cycle hooks which takes maintenance time. Try not to copy what is available in theprops
into thestate
. For example, to keep track of which row is selected in a table, you can save the entire row (as a big object) in thestate
or just save itsindex
(as a number). Saving the entire row is tempting, you may think it is easier to access the row bythis.state.selectedRow
instead ofthis.props.rows[this.state.selectedRowIndex]
. But the first approach leads to unknown consequences down the road. This may not totally be a performance tip, but having it in mind helps to reduce unwanted consequences tremendously.. - Use JSS (or its one of its derivatives like
withStyles
inmaterial-ui
) instead of inline styles. Whenever you are using inline styles, you are creating a JS object. It might be OK for one-time usage. But for example, using inline styles inmap
s would be a terrible idea. Extract inline styles into their own object and reuse them, or better, use JSS for even more performance. - Reuse functions just like other objects. For example, when you want to pass a function and use it inside a map, instead of creating the function inline, like
submit={() => doSomething(note.id)}
, create the function in the class and pass the reference likesubmit={this.doSomething}
. If you create the function inline, you are changing the component’s prop each time (because the newly created function has a new reference) and a useless render will be triggered. - Now that the component is small and the props are well known and documented (use
flow
orprop-types
), you can easily implementshouldComponentUpdate
and boost performance. - You can use
PureComponent
instead ofComponent
wherever possible. Use it with care and enough test as the last resort. Make sure shallow comparison of all props is what you want. If allprops
are known you can implementshouldComponentUpdate
yourself instead of usingPureComponent
. - UPDATE: Avoid having states up in the hierarchy. Use redux. When you have a state up in hierarchy, updating it will cause a render across the whole tree. You can store this state in the redux and connect it only to the component which needs it. So only the component will get updated when the state in redux changes.
In the end, always analyze the performance in Dev Tools while fine-tuning. Sometimes it surprises you by showing that the things that you may have considered beneficial for performance actually have made it worse.