React Patterns — Improving Performance and Avoid Antipatterns

John Au-Yeung - Jan 21 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

React is a popular library for creating web apps and mobile apps.

In this article, we’ll look at how to improve the performance and avoiding antipatterns when we create React apps.

Reconciliation and keys

We’ve to add a key to the key prop that’s unique.

Otherwise, React can’t keep track of the list items properly.

For instance, we can write:

{items.map(item => <li key={item.id}>{item.name}</li>)}
Enter fullscreen mode Exit fullscreen mode

We got to have an id property that’s unique with for each items entry.

The items that are inserted can’t be tracked without a unique ID in the key prop.

useEffect

We should watch the items that we need to watch to update a derived value.

To do that we use the useEffect hook.

For instance, we write:

useEffect(() => {
  doSomething(foo);
}, [foo]);
Enter fullscreen mode Exit fullscreen mode

Now we call doSomething only when foo updates.

This is the hooks equivalent of shouldComponentUpdate and componentWillReceiveProps .

It works with both props and state changes.

Stateless Function Components

Stateless function components don’t give any benefits with regards to performance.

It just helps us make presentation only components to separate logic from components with states.

useMemo

We can use the useMemo hook to store results from expensive computations.

For instance, we can write:

const memoizedValue = useMemo(() => compute(a, b), [a, b]);
Enter fullscreen mode Exit fullscreen mode

Now React won’t compute the value again unless a or b changed.

Refactoring and Good Design

We should have states with descriptive names.

items is a good name for a state that stores some items.

If we have something more specific then we should name it with that.

We should only render when something changes.

If props and state change, then we render.

Immutability

We should make things immutable when we can,

This way, they can’t be mutated accidentally.

Then we can avoid this kind of bugs, which may be hard to trace.

To avoid mutation, we can make a copy of an object and then change it.

We can use Object.assign or spread to do that:

const newObj = Object.assign({}, obj, { foo: 'bar' });
Enter fullscreen mode Exit fullscreen mode

or:

const newObj = {...obj,  foo: 'bar' };
Enter fullscreen mode Exit fullscreen mode

Likewise, we can do the same with arrays.

For instance, we can write:

const newArr = [...arr, 1];
Enter fullscreen mode Exit fullscreen mode

We used the spread operator to spread the arr array entries into a new array and add 1 to it.

Initializing the State using Props

We shouldn’t initialize the state using props.

Instead, we should watch for prop changes and then update the state accordingly.

This way, we’ll make sure our props are updated with the state.

To do that, we use the useEffect hook as follows:

useEffect(() => {
  setBar(foo);
}, [foo]);
Enter fullscreen mode Exit fullscreen mode

If foo is a prop, then we can set the bar state with setBar by calling it with foo so that the bar state is updated when foo is updated.

Mutating the State

Also, we shouldn’t mutate the state directly.

If we have a state, then we shouldn’t assign it with a new value direcyly.

Instead, we call the function to set the state.

For instance, we can write:

setCount(2);
Enter fullscreen mode Exit fullscreen mode

top set the state, where setCount is the function returned by useState to set the count state.

Or we can write:

setCount(count => count + 1);
Enter fullscreen mode Exit fullscreen mode

if we want to set a state based on the previous count state’s value.

We should do that as little as possible to improve performance.

Using Indexes as a Key

Indexes shouldn’t be used as the key if possible.

This is because tracking can’t be done properly with indexes as keys, then if we modify the array of elements or components, then we would have problems.

The best value for the key prop is a unique ID of the item.

Spreading Props on DOM Elements

We should avoid spreading props to DOM elements to avoid spreading unknown HTML attributes, which is a bad practice.

We may get errors from React telling us to remove unknown attributes.

Instead, we should just write them out explicitly unlike props.

Conclusion

We should think about performance and antipatterns when we’re writing React components.

It’s hard to create components that are speedy and do everything we want.

But if we take into account some good practices, we can do it easily.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .