Brushing up on React best practices

Keep your code clean, modular and DRY

Part of an ongoing series Brushing up on React.

Photo by Kevin Ku on Unsplash

Container and View components a.k.a. Smart and Dumb components

This by far my favorite React pattern and enforces the divine coding rule of single responsibility. The idea is simple: encapsulate your logic i.e. business logic or fetching data into a component (container or smart components) and your presentation logic into another component (view or dumb component) who’s only responsibility is to take data and render html. The container component will do all the heavy lifting and render the view component passing in the required data.

Dan Abramov used to be a huge proponent of the pattern but has toned down his preaching after the invent of React Hooks. What I understand from his update in his Medium post (link below) is that he is against forcing the pattern, which makes sense. Never force a pattern. Only follow it when it makes sense. Patterns, just like languages, are tools to achieve certain outcomes.

Even with Hooks, I like this pattern. I love the idea of Single Responsibility Principal for components. Smart and Dumb components mean smaller components, which in turn, means they are easier to understand and write tests for. If I want to write up tests for my presentation logic, I should not need to worry about mocking a bunch of stuffs to get around Hooks. If you bundle your presentation and core logic together, you would have to mock around the whole component no matter what you are trying to test.

Learn more from the man himself: smart vs dumb components.

Higher Order Components

The name higher order component comes from higher order functions, which takes other functions as arguments. HoC takes in a component as an arg , adds some logic and returns another component with the added logic. The idea is that the 'added logic' can be reused agnostically with any other component, thus keeping your code 'DRY'. HoC also jives with the whole functional nature of React.

Controlled Components

Controlled components deal with HTML form elements such as <input/> and <select/> . You wrap these elements with a custom component and dictate their behavior, like what happens when a user clicks on a radio button, using the state of the wrapper component. Why you ask? It has something to do with getting data from DOM more efficiently. Probably. Read more from here.

A component should be a self contained module

The whole philosophy behind React is that you create reusable and modularized components. This ensures maintainability and consistency throughout the app. I like to keep my component source code, test code and css files in the same dir. It makes it easier to find everything you need for that component. You don't have to go on a wild hunt. Moreover, it reinforces the idea that your component is the source of re-usability. If you want to use your component in a different project, you can just copy that directory and use the component. Or better yet, publish your component library and then re-use the library in your whole product suite.

Create a wrapper 3rd party components

This helps with consistency throughout your app. Let’s say you are using a third party carousel component. Wrap it in a custom component and add your own modifications and configurations. Now when you need to use it again somewhere else, you can just use . You don’t need to add your modifications or configurations again. If you do want to use different config, just pass them in as props.

import Carousel from 'carousel-number-one';

import './myCarousel.less'; const carouselConfig = {

alignment: 'vertical'

}; export default function MyCarousel(props) {

return (<div className='my-carousel'>

<Carousel config={carouselConfig}/>

</div>);

}

Use propTypes and defaultProps

One of JS’s curse (or blessing, depending who you ask) is that it’s not type safe. Of course you can use TypeScript, but that’s not a part of this doc. One way you can add a little bit of type safety to your components and make them more robust is by using propTypes.

Use defaultProps which are static class properties of React.Component that the component uses if no props are passed to it.

When updating state, always use prevState

Its very easy to forget that setState is async, and therefore the current state might not be what you think it is. So when you call setState, the safest bet is to use the prevState to update the newer state.