Skip to content

Instantly share code, notes, and snippets.

@imdongchen
Created October 2, 2018 14:53
Show Gist options
  • Save imdongchen/c34123cd43b1f91d5aa478865cce6c55 to your computer and use it in GitHub Desktop.
Save imdongchen/c34123cd43b1f91d5aa478865cce6c55 to your computer and use it in GitHub Desktop.

These four tips are lessons I learned recently. Just want to share in case you find it useful.

Tip One: Use conditional rendering as first choice

When a component is only rendered in some condition, you can either do conditional rendering

https://gist.github.com/cf100928c4bc0f753fb6d334ee486820

Or use class name /css to toggle hiding of the component

https://gist.github.com/83739f48cff305f9df4959cf872b36c9

Usually we should use conditional rendering. It is faster because no component is generated and thus React does not need to do rendering / reconcilation / DOM operation. In contrast, in the css approach, React still needs to create the DOM and do all the updating even though it’s never shown.

Another benefit of conditional rendering is dynamic code splitting. If we enable code splitting by component, the component chunk file will only be downloaded when the condition is true in the conditional rendering. When the condition is false, the component function is not executed, and thus the chunk containing the component will not be requested. This is especially useful for components that only show in edge cases (e.g. error dialog). Most users won’t see these components, and thus don’t need to download these scripts.

One case that we probably want to go with css approach is when the component will be toggled frequently. Using css to hide and show the DOM will be cheaper than adding and removing the DOM on a frequent basis.

Tip Two: Restrain from prop spreading

ES6 provides a convenient way to destruct object, and react supports this syntax as well. You can do

https://gist.github.com/1d20b326f4e21f96ee6b31b6c42f54a3

to pass all fields in props to a component. The benefit is that this saves code, especially you have a long list of props for the component. But I’d say the harm outweighs the benefit. Prop spreading makes it difficult to identify what props are exactly passed and what props are really needed for the component. When refactoring, it’s difficult to tell whether it’s safe to remove a prop. For example,

https://gist.github.com/46ad6f4fdfab449bbd33931b0f1336ff

In the Profile component, prop gender seems not to be used anywhere. With a command F search but it is actually implicitly passed to Detail. During refactoring, it is likely that one will remove gender from the connected profile component, which will cause Detail to err.

Tip Three: Decompose into smaller components

Did you ever write a component like this?

https://gist.github.com/2bfecea42c2649b4eeea4658d1d2ec68

Since each time a new function instance is created in the click handler, the InnerComponent always receives a new prop value, so it always re-renders. Instead, they suggest declaring the function separately and referring to the function in the click handler. Because it is the same function reference, the component won’t re-render.

https://gist.github.com/d084dcf15f6ab4f631fb92f116441af0

But that’s actually not true. Avoiding the inline function is only half of the story. Whether InnerComponent will re-render also depends on how it is implemented. If InnerComponent is a functional component or a regular class component, it will always re-render, regardless of prop change.

https://gist.github.com/537a7e88c132a8daf00b7601331d4d66

Only when InnerComponent implements shouldComponentUpdate or when it extends from PureComponent will it compare prop changes. In other cases (functional component and regular class component), it will always re-render regardless of prop changes.

So is this bad? Shall we always use PureComponent or implement shouldComponentUpdate?

First, re-rendering is not bad at all. In fact, re-rendering is pretty cheap. All it does is to create a virtual DOM tree in memory, but it does not touch the real DOM, which is why it is fast. After the virtual DOM is created, it compares with the existing one. This process is called /reconciliation/, which is not expensive either. If it decides that DOM needs to be updated, react will /commit/ the change and manipulate real DOM, and that is what could drag down performance. Therefore, we don’t really need to worry about re-rendering most of time; just let react decide whether to update DOM or not.

Second, PureComponent or shouldComponentUpdate can actually harm performance. Most of time our components do need to update. In those cases, the extra prop comparisons only adds additional computing /on top of/ re-rendering. Read @Ryan’s React, Inline Functions, and Performance – componentDidBlog to learn his story.

Third, PureComponent or shouldComponentUpdate could lead to unexpected behavior. Imagine you have a pure component as a parent component. When it decides not to re-render (because no prop changes), its child components will not change either. It may result in UI failing to update with user interaction. That’s one reason why pure components are not the default behavior.

In summary, because re-rendering does not necessarily hit performance (and most often doesn’t) and also because of the potential risk of pure component, it is not a good practice to pre-optimize components. Only do it when you do notice a performance issue.

Summary

These are the four lessons I learned for React recently, somewhat random, but hopefully useful! To reiterate:

Tip #1, Use conditional rendering because it is usually faster and good for lazy loading Tip #2, Restrain from prop spreading because it is bad for readability and refactoring Tip #3, Decompose into smaller components if you have a sub render method because it makes component easier to read and test Tip #4, Don’t pre-optimize component performance because React is usually fast enough!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment