2019 ReactJS Best Practices & Design Patterns

image for article

For the past five years, ReactJS has been rapidly increasing in its popularity and by the beginning of 2018 it became more popular than jQuery, at least in terms of Google searches. We will not be comparing tools in terms of their demand in the search engines; however, that gives us a clear understanding that the ReactJS library is definitely popular. With that being said, let’s talk about using ReactJS to create better Front-End apps.

What makes ReactJS so popular, besides the fact that Facebook created it? We think it’s due to ReactJS being straightforward to work with. It is easy to learn and it’s optimized for performance by using its virtual DOM. By implementing virtual DOM, ReactJS offers a rendering engine a way to quickly re-render only those elements that need to be updated. As a result, ReactJS developers are getting apps that are fast and pleasant to use.

ReactJS is a library that uses JavaScript to create apps. To start building apps in ReactJS, you need to learn its API and know JavaScript. JavaScript is probably the most popular programming language these days. ReactJS also enables developers to model and describe an app in UI components. So you just say what to do and ReactJS knows how to do it.

Here are some trends for the past five years from Google:

One of the main ReactJS concepts is that you create reusable, cohesive components that can be put together and form an app. Each component may have its own state unless it is state-less (more about this later). ReactJS collects all your components into one bucket and applies some optimization techniques such as virtual DOM to render the app in your browser efficiently.

Let’s start by clarifying what a component is and what it is not. The component is a self-sufficient, independent part of the UI. Each component can embed other components, where each one has its state and API. By convention, you should keep your component-related code inside one specific folder. Keeping all the files for each component in a single folder allows you to create reusable components so that you can use them in the other apps.

Types of ReactJS components

There are four main types of ReactJS components:

  • State-full or class-based components;
  • State-less or function-based components;
  • Presentational (or high-order) components;
  • Container components.

A good structure for you component is displayed on with green:

Image alt

State-full components or class-based components

A state-full component has its state and data associated with the state. You can pass data inside this type of component via state or props objects. State-full components are also harder to support as they persist some data and may change the global state of the app. Also, state-full components are most often class-based components that have a constructor (it’s considered a best practice to set state for your component in the constructor).

Here is an example of the state-full, class-based ReactJS component:

Image alt

Props are immutable and are one-way bound to a state, and this is why you cannot change them within your component. You use props to set a state for the component and to render its UI. If you try to change props in your component, you will get a Type Error:

Image alt

State is an object that is exposed to a component. State scope is limited to inside the component where it is declared. Components can initialize state and pass it to another component. We can declare a state in two ways, using the constructor or declaring state property. With the second case, that is just syntactic sugar, and the transpiler (such as Babel) will turn your state property declaration into the constructor for you under the hood. State-less components or function-based components and what React Hooks is for Function-based components are just simple JavaScript functions. Function-based components return a ReactJS element or a collection, which can be a ‘partial component’ like <>...</> or a fully function-based component with the logic and embedded components. Since you cannot use a constructor in a function-based component (well, actually you do, since ReactJS v16.8), you cannot make your component state-full. It is state-less because you cannot persist any data in these types of components. Most often you pass in props to the function-based component to render its UI.

Here is an example of the state-less, function-based ReactJS component:

Image alt

From the performance point-of-view, there is practically no difference between using class-based components and using function-based components. ReactJS rendering mechanism is smart enough to optimize that for us.

Function-based components are easier to work with and more comfortable to test. This is why the community of ReactJS developers will nudge you to write function-based components instead of class-based ones. State-less function-based components have some limitations and essentially must have one global place to manage state. That is different from the ReactJS paradigm of writing components (for more details, see below).

To enable developers to write state-full, function-based components and at the same time give the ability to use state and component life-cycle methods, React v16.8 added a new feature called React Hooks. Essentially, React Hooks is an attempt to remove class-based components. With React Hooks you can write state-full function-based components without using classes. Probably we will see class-based components eliminated with Hooks at some point in the future.

React Hooks also aims to simplify application design by avoiding components that do not have or do not need constructors although they are declared as classes. Most often you work with state-less components if you think about the ideal design of your app. When we build ReactJS apps for our clients, we usually use a thin layer between our component representation and the application’s logic. This allows us to decouple the visual representation of the component from its behavior.

What is the «Data Down, Actions Up» design pattern? Essentially it means you have a high-order component (HOC) which accepts the data in its props and passes that data down into its view or nested components. To interact with the component, users trigger actions such as pressing a button and the component responds to that interaction by emitting events. So to say, it triggers an event up, in the opposite direction to how that data was passed. Those events or actions are passed up to a parent component. The parent component triggers another action that changes a global application state. High-Order Component High-Order Component (or HOC) is essentially a design pattern, also known as a Decorator Pattern. In ReactJS, a HOC is a component that wraps another component by adding extra functionality or extra properties. This allows abstraction from some commonly used logic and keeps your code DRY. It is a means in ReactJS to distribute complex component structure between other components and a way to decouple your application logic and UI. For instance, you may use container component as a HOC for your presentational Button component.

Here is an example of the HOC ReactJS component:

Image alt

Container components

Container components, on the other hand, have logic to set state or have functions to emit events up to a parent component. The general rule of the thumb is to keep your component as simple as possible with a Single Responsibility Principle design principle in mind, which essentially means your component must do one thing, but do it well. Most often, these types of components are the HOCs that accommodate few presentational components. Presentational components Writing simple components may reduce your overall application complexity. Here is where presentational components come into play. These components should have minimal to no logic. Presentational components accept data and emit events to a callback that they receive as part of its props. Essentially, this type of component renders UI and executes a function that was passed into it when some action in its UI happens. This type of component is a building block and is sometimes referred to as a Low-Order Component (or LOC).

Best Practices List

  • We have created the list of rules, to help you to create a better ReactJS app:
  • Consider using TypeScript in your apps if you do not do it already.
  • Use the create-react-app generator to bootstrap your ReactJS app.
  • Keep your code DRY. Don’t Repeat Yourself.
  • Avoid having large classes or components.
  • Use more robust managers to manage application state, such as Redux.
  • Use event synchronizer, such as redux-thunk, for interactions with your Back-End.
  • Avoid passing too many attributes or arguments. Limit yourself to five props that you pass into your component.
  • Use ReactJS defaultProps and ReactJS propTypes.
  • Use linter, break up lines that are too long.
  • Keep your own jslint configuration file.
  • Always use a dependency manager with a lock file, such as NPM or yarn.
  • Test your commonly accessed code, code that is complex and prone to bugs.
  • Write more tests that give more test coverage for your code with a little effort and test code to ensure its proper functioning.
  • Every time you find a bug, make sure you write a test first.
  • Use function-based components by starting to use React Hooks, a new ReactJS way to create state-full components.
  • Use ES6 destructuring for your props.
  • Use conditional rendering.
  • User map() to render collections of components.
  • Use partial components.
  • Name your event handlers with handle prefixes, such as handleClick or handleUpdate.
  • Use onChange to control your inputs, such as onChange={this.handleInputChange}.
  • Use JEST to test your ReactJS code.

We have mentioned event synchronizers, such as redux-thunk. ReactJS v16.3 introduced a new feature called React Context API. Part of its functionality is to mimic redux-thunk functionality and synchronize events with ReactJS means. That is a feature that is in high demand, as nearly any ReactJS application talks to Back-End and needs to synchronize requests and events. We will keep our eye on that API and will keep you posted with updates.

Here is an example of using defaultProps and propTypes:

Image alt

Here is an example of the output provided by the JEST testing framework:

Image alt

We at Konstankino hope this article sheds some light on ReactJS best practices and patterns that are very popular in 2019. Good luck with your ReactJS development!