The philosophy of React: Keeping render() light
A core concept behind React is the idea of a lightweight render()
function.
Every time a React component’s state or props change, it runs its render()
(unless, of course, the component has a shouldComponentUpdate()
function that returns false). This means that in some components, especially those that listen to mouse, scroll, or window resize events, render()
is called extremely frequently, on the order of several times per second. This high frequency means that in order to keep a webapp responsive to user input, render()
must be kept lightweight.
Consider a component that makes 2 API calls, receives two arrays of data X and Y, merges them into array Z, and then renders a single array of list items A based on those data. (X and Y may be an array of posts and an array of comments, for example.)
The simplest way to construct this component is to put X and Y in the component’s state when the API call returns, and then to construct Z from X and Y inside render()
.
However, this method requires that X and Y become merged to form Z inside render()
. Because array merges are usually O(n2) or worse in terms of expensiveness, this method can lead to a heavy render()
if X and Y are large, and therefore to a sluggish and unresponsive component.
Instead, one could perform the merge immediately after the component receives X and Y, and then put the resultant Z in state instead. With this method, the expensive array merge happens only once, and all render()
must do is map Z to A. Because mapping functions are usually O(n), the result is a fast and responsive component, even if X and Y are very large.
The difference between these two approaches may not be very visible when working with small data sets, but one should always design for scale. By keeping render()
lightweight, you are ensuring that your component will function for most any size of input data.
Happy hacking!