In this post, let’s go over some simple tips that will help you write cleaner React components and scale your project better.
Avoid passing props with the spread operator
Let’s first start with an antipattern that you should avoid. Unless there’s a specific and justified reason to do it, you should avoid passing props down the component tree using a spread operator, like so: {...props}.
Passing props this way indeed makes writing components faster. However, it also makes it very hard to pin down the bugs in your code. You lose confidence in your components, which makes it harder to refactor them, and as a result, the bugs will start creeping in a lot sooner.
Wrap your function parameters in an object
If your function accepts multiple parameters, it’s a good idea to wrap them in an object. Here’s an example:
Writing your function signature this way provides several notable advantages:
You no longer need to worry about the order in which you’re passing your arguments. I’ve made this mistake several times, where I would introduce a bug and pass function arguments in the wrong order.
For editors with IntelliSense configured (most of them nowadays), you’ll get a nice autocomplete feature for your function arguments.
For event handlers, use functions that return handler functions
If you’re familiar with functional programming, this technique resembles currying since you’re pre-setting some of the parameters ahead of time.
Using this simple strategy, your components become more declarative and easier to comprehend. It also makes it simpler to extend the logic and add more items to it.
Hook components
I find this pattern useful, as long as you don’t abuse it.
You might find yourself using some of the components all over your app. If they need a state to function, you can wrap them with a hook that provides that state. Some good examples of such components are popups, toast notifications, or simple modals. For example, here’s a component hook for a simple confirmation modal:
importReactfrom"react";import{useConfirmationDialog}from'./useConfirmationDialog'functionClient(){const{Dialog,onOpen}=useConfirmationDialog({headerText:"Delete this record?",bodyText:"Are you sure you want delete this record? This cannot be undone.",confirmationButtonText:"Delete",onConfirmClick:handleDeleteConfirm,});functionhandleDeleteConfirm(){//TODO: delete
}consthandleDeleteClick=()=>{onOpen();};return(<div><Dialog/><buttononClick={handleDeleteClick}/></div>);}exportdefaultClient;
Abstracting the component this way saves you from writing a lot of boilerplate state management code. If you want to learn more about useful React hooks check out my
post here
.
Splitting components
The following three tips are about intelligently splitting your components. From my experience, keeping your components small is the best way to keep your project manageable.
Use wrappers
If you’re struggling to find a way to split your big component, look at the functionality each element of your component provides. Some elements are there to provide a distinct functionality, like drag and drop handlers.
Here’s an example of a component that implements drag-and-drop using react-beautiful-dnd:
As a result, it’s easier to glance at the component and understand what it does at a high level. All the functionality for drag-and-drop lives in the wrapper and is much easier to reason about.
Separation of concerns
This is my favorite method of splitting larger components.
In the context of React, the separation of concerns means separating the parts of the components that are responsible for fetching and mutating the data and the ones responsible purely for displaying the element tree.
This method of separation of concerns is the main reason the hook pattern was introduced. You can and should wrap all the logic that manages APIs or global state connections with a custom hook.
While there’s nothing terribly wrong with writing a code like that, it’s not a good practice to follow. There are no downsides to moving ItemDisplay to a separate file, and the upsides are that your components are loosely coupled and easier to extend.
Writing clean code for the most part comes down to being mindful and taking the time to follow good patterns and avoiding antipatterns. So if you take the time to follow these patterns, it will help your write cleaner React components. I find these patterns very useful in my project and I hope you do as well!
If you’d like to get more web development, React and TypeScript tips consider
following me on Twitter,
where I share things as I learn them.
Happy coding!
Share on
WRITTEN BY
Iskander Samatov
The best up-to-date tutorials on React, JavaScript and web development.