5 React Component Best Practices You Should Know

Destructure props, named components, and more

Caelin Sutch
Better Programming

--

decorative: glass ball
Photo by Michael Dziedzic on Unsplash

React is meant to be an incredibly flexible software library, with no clear best practice when it comes to application structure or design. However, there are still some best practices and general rules that developers can use to write better React code.

Software architecture is meant to be productive and flexible for developers. The goal of good software is to keep the codebase maintainable and modular if any modifications or additions are needed.

I’ve put together some of the best practices I’ve picked for writing good React code, ones that have proven to be effective in applications large and small.

However, remember that these aren’t rules, these are opinions on what I’ve found the best practices are for writing good React code.

We’ll be divvying this up into a couple of sections and parts to make it easily digestible.

Components

We’ll be starting off talking about components and their structure.

Name components

Always name your React components. It makes it easier to read error stacks, use React dev tools, and search through a large code base.

It also helps autocomplete find the component you want to use!

// This is an unnamed component. Don't do this
export default () => <div>...</div>
// This is a named component :)
export default function Card() { return <div>...</div> )

Write consistently organized components

Whatever style you choose to write components in, be sure it’s consistent throughout the entire code base. This means organization, like where you put your helper functions or the export, or function syntax (like I did above) versus lambda functions. If the code looks and feels the same for every file, it makes every developer's life easier and more productive.

Separate constants and helpers into different files

My objective when writing React components is to keep each file under 200 lines. This means moving helper functions into a separate component.utils.ts file and constants into acomponent.constants.ts file to make the component smaller and easier to read.

This is particularly effective when working with large state objects:

With this structure, it becomes much easier to understand even really complex components since they’re modular and broken into bite-size chunks.

Destructure props

Most React components are basic functions. They take in some props and return markup. The majority of the time, you use the arguments as passed in directly, so it makes sense to destructure props so it’s not repeated everywhere.

Unless your component has managed states, it almost always makes sense to break down function parameters into individual keys:

Don’t pass a ton of props in

Complex components are harder to read and maintain. If you’re passing in a lot of props, really consider whether or not they can be broken down into more pieces. The number of props passed in is usually correlated to how much the component is doing.

If I have above six props being passed in, I normally know there’s some way to break down the component into smaller chunks. In some cases, like inputs, it’s OK to have a large number of props (they require a lot of values); otherwise, extract and modularize.

Avoid nesting render functions

This is my least favorite practice to see in the code I review. When extracting markup and logic from a component, don’t create a function living inside another component. Nesting components is almost always a bad idea and makes code hard to read.

Move the new component to its own files and rely on props rather than using a globally nested state.

Conditional rendering practices

There are a couple of great ways to do conditional rendering. Short circuit operators are a very short and easy way to do conditional rendering:

Here’s a great Stack Overflow post on short circuit operators that explains some more ways you can use these to write cleaner code.

Assign default props when destructuring

When using default props, you can use the defaultProps property on a component, but don’t. This makes the component harder to read since the values aren’t declared where the keys are defined.

I prefer assigning default values when destructuring the props. It also makes it easier to read the code from top to bottom without having to jump around to find the default props, keeping the definitions and values together.

Prefer passing objects

One great way to limit the number of props passed is to pass an object instead of a set of primitive values. For example, rather than passing each aspect of a user, you can group them together. Down the road, if the user gains extra data, this function won’t have to be modified to accommodate that.

Move lists into separate components

One of the most common operations in React is looping through a list to generate components using a map function. However, in components, this can lead to some messy code: the additional markup, indentation, and Javascript, none of which helps with readability.

When you need to map over elements, extract them into their own listing component. The parent component doesn’t need to know about the details if it’s only displaying the list, and this makes the parent a lot easier to read.

However, if a component's main responsibility is to display a list, keep it. There should only be a single mapping per component. If there are multiple, then they should all be extracted to their own components.

Conclusion

Remember that these are just suggestions, and the best practice is the one that works best for your team. In the next part, we’ll be talking about best practices for state management.

--

--