Best practices in React

Murat Catal
Oct 12 · 6 min read
Photo by Artem Sapegin on Unsplash

React is one of the most popular framework among front-end developers. You may developed many React applications or you may be a newbie, each time we want to build best one. In that article, some of the best practices are evaluated in terms of design, bindings and new concepts like hooks.

Hope you’ll enjoy :)


Component Design

Before dying into component design, let’s look how components are rendered in React in one sentenced A component is rendered;

  • When its prop changes
  • When its state changed
  • When its parent rendered, each child are re-rendered

The point that will be described here will about 3rd item. Let’s point the problem then describe how to solve the problem.

<ParentComponent>
<ChildComponent />
</ParentComponent>

Say we have a component design like above example. When ParentComponent re-rendered, it’s child component will be re-rendered regardless off it should re-rendered or not. This will lead unnecessary re-renders in child and will down your frontend’s performance.

What should we do?

Avoid extending your components from React.Component and try to choose functional components as you can now has hooks’s power.

You have 3 options to avoid unnecessary re-renders.

Although it’s said that React is really fast and do not afraid of unnecessary re-renders that much, it depends on your project. If your project has a real-time update and gets data so frequently, you should start to think about unnecessary re-renders.

  • If you extend your components from React.Component, override shouldComponentUpdate function. This function returns a boolean value and according to return value, your component will be re-rendered or not. However, the problem is that you must compare each prop value with previous values to check whether something changed and your component will be re-rendered or not. So, whenever you added a new prop, you must also add that comparison into your check-list.
shouldComponentUpdate(nextProps, nextState){
return nextProps.id !== thisp.rops.id || nextState.name !== this.state.name;
}

Do not forget to add new state and prop values into your comparison statement

  • Extend your components React.PureComponent. PureComponent internally runs shouldComponentUpdate function. However, the problem with this is, it may return true always if your prop or state model consist of complex nested JSON.

React.PureComponent is good if your state and prop values consist of primitive values or not nested JSON objects. For nested JSON models, it may return true always and makes unnecessary re-renders.

  • What i’ll recommend is using functional components, and forget about items that is mentioned above. More simple components without thinking Component’s life-cycles.

With hook’s implementation, you can prefer using Functional Components as much as you can which will give you more performance over React.Component

You can check working example on codesandbox. Each time you click on button, you can see which component’s are re-rendered on console.

Live example on codesandbox


Abstraction

React changes developers’ thinking way. It forces front-end developers to create re-usable components by advising you to divide your components into smaller pieces.

Do not afraid of diving your components into smaller pieces. Create as small pieces as you can. These will help you create re-usable components more.

Higher Order Components (HOC)

HOC are functions that returns a new component by adding new features but without changing wrapped component’s internal state. Component’s must give same output for same inputs for consistency. Thus, when you change component’s internal state in HOC, you can lose consistency in your component’s output.

const withReversedLabel = WrappedComponent => {
return class extends React.Component {
render() {
const label = this.props.label
.split("")
.reverse()
.join("");
return <WrappedComponent label={label} />;
}
};
};

Live example on codesandbox

Wrapper Component

A wrapper component differs from HOC by its syntax. In HOC, you return a new component by adding new features to existing one while in Wrapper Component Design, you render child by adding new features.

const Card = ({ children }) => <div className="card">{children}</div>;
const Content = () => <div>My content</div>;
const Content2 = () => <div>My content 2</div>;
function App() {
return (
<>
<Card>
<Content />
</Card>
<Card>
<Content2 />
</Card>
</>
);
}

What you gained?

  • You got more component-based syntax
  • You can restrict for child count in WrapperComponent
  • You just created a template card component and you can render whatever you want in your CardComponent

Live example on codesandbox

Render Props

In this pattern, you can share one component’s properties within another component. It’s similar to HOC but more powerful with its syntax.

Let’s say you have a component named Fetch which you can manage your rest calls. In this component, you are handling loading, error and data states. Another component, called Students, need to fetch data and you do not want to include that business into Student component but want to use Fetch component.

Render props is a pattern where you send your component as a functional parameter into wrapper class.

<Fetch 
url="abc.com"
>
{({ loading, error, data }) => {
if (loading) {
return <div>Loading!</div>;
} else if (error) {
return <div>{error}</div>;
} else {
return <Student data={data} />;
}
}}
</Fetch>

Live example on codesandbox


Function Binding

Let’s define problem first. Most of developers, started to use arrow functions because of its simplicity for not binding in constructor and it is more performant than binding function in constructor. However, it has performance impact if you use it wrong.

// bad examplefunction MyComponent = () => {
return <button onClick={() => callMe()}>Click me</button>
}

The problem here is, each time your component re-renders, a new reference will be created for your callMe function.

To solve this issue, you can move your function out from your onClick event handler.

function MyComponent = () => {
const handleClick = () => console.log(1);
return <button onClick={handleClick}>Click me</button>
}

But how can i bind a custom value when i used my function like above?

Let’s say you have a list and you want to bind your id with your button’s onClick function.

function App() {
const handleClick = id => console.log(id);
return datas.map(data => (
<button onClick={handleClick.bind(null, data.id)}>Click me!</button>
));
}

Live example on codesandbox


Using Hooks & Memorize

Hooks come into React life cycle within v16.8 for functional components to give power of class components. There are lots of built-in hooks which you can use such as useState, useMemo, useCallback etc.., and you can also define your own hooks for using within functional components.

useState

Before hooks, functional components were stated as Stateless Functional Components because they did not have states. However, things changed after hooks come into life and Stateless Functional Component’s name changed to Functional Components.

How to use useState?

The important things is while using useState is it behaves different than this.setState() function which is used in class-based components. When you use this.setState() function, it merges sent value with its already stored state while useState just overrides its whole state with new one.

In simplest way, the usage of useState is shown below.

const [myState, setMyState] = useState(1); 

Do not forget to initialize your state values

React.memo

As described in first section, whenever a parent component’s state/prop changes, all its children will just re-rendered. However, there is a function defined in React which you can use to avoid from unnecessary re-renders.

React.memo just memories component’s props and internally whenever your props changes re-renders your component. It’s similar to shouldComponentUpdate method described for class based components, but this method is for only functional components.

You can see on live example. There is a parent component and 2 children, one is wrapped by React.memo and the other one is not. Whenever you will click on parent’s button to trigger a state changes, you will see that functional component without React.memo will have re-rendering although its state or prop not changed.

Live example on codesandbox


If you like my articles, you can support me by clapping and following me.
I’m also on
linkedin, all invitations are welcome.

JavaScript in Plain English

Murat Catal

Written by

Enjoys sharing!

JavaScript in Plain English

Learn the web's most important programming language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade