React is a JavaScript library that speeds up application development thanks to reusable components whilst ensuring high app performance. It also allows for automatic testing, which reduces the number of bugs and decreases overall application maintenance costs. To fully use React capabilities in web development, it is good to follow best practices and use battle-proven tools. Hence this blog post that summarizes React best practices based on our experience.
While building an app, it is good to assume the maximum size of a component. In small components, it is easier to apply the principle of the Separation of Concerns (SoC), i.e., separating an application into distinct modules addressing different functionalities. It is also easier to follow industry guidelines like WCAG or optimize a webpage for SEO.
If your component exceeds the size limit, you should consider dividing it into smaller, more specialized parts. Components should also be divided according to their functionalities or the layer in which they are used such (e.g. presentation layer, business logic layer or data access layer, persistence layer, etc.). If there are problems, you can use an advanced React technique called Higher Order Components (HOC) that allows you to reuse component logic.
From a business perspective, keeping React components small and function-specific is also very important, as it considerably reduces the costs of application maintenance.
A clear distinction between these types of components will allow you to decide whether you need a new component or not. And this drastically reduces the maintenance and modification costs of the web application.
Therefore, TypeScript is an ideal addition to React-based applications. It can be used in many places, from supporting application API, through app logic, to the smallest UI components. TypeScript ensures the integrity of data types in the entire web application and allows you to avoid type mismatch errors. Additionally, it speeds up the process of implementing modifications in already existing components, pointing out places where type modification is required.
With TypeScript, you can easily use app elements that already exist, supporting IDE (Integrated Development Environment) with additional information. This makes a web app more reliable when implementing new functionalities and reduces maintenance costs and the time needed to implement new features.
#1 Use small, functional components
The size of the components matters. Smaller components are easier to understand and use, which allows you to onboard new people to the project much faster. It is also easier to test them, which shortens the time needed to write tests and decreases the number of bugs.While building an app, it is good to assume the maximum size of a component. In small components, it is easier to apply the principle of the Separation of Concerns (SoC), i.e., separating an application into distinct modules addressing different functionalities. It is also easier to follow industry guidelines like WCAG or optimize a webpage for SEO.
If your component exceeds the size limit, you should consider dividing it into smaller, more specialized parts. Components should also be divided according to their functionalities or the layer in which they are used such (e.g. presentation layer, business logic layer or data access layer, persistence layer, etc.). If there are problems, you can use an advanced React technique called Higher Order Components (HOC) that allows you to reuse component logic.
From a business perspective, keeping React components small and function-specific is also very important, as it considerably reduces the costs of application maintenance.
#2 Keep application business logic and UI layers separated
The HOC technique also allows you to separate application layers, especially business logic from the user interface (UI). This principle speeds up the entire modification process, as you can change both app business logic and its look and feel more easily. The number of app components is also smaller, which simplifies their maintenance. What’s more important, we stick to the DRY principle (Do not Repeat Yourself) by not multiplying app logic in its different components. This works both for adding a new element (e.g., a button or menu) and for reusing the entire forms or functionality logic. Keeping business logic and UI layers separated also brings an additional benefit. UI components built this way can be easily presented in the form of a component set (e.g. by using Storybook) or library and discussed with the UI/UX team or manually tested in a secure environment. Additionally, thanks to such a library, a new team member can be introduced to the project faster.#3 Have a clear distinction between reusable and business-specific components.
At the application level, it is important to separate reusable components from those responsible for business logic. Reusable components are used to build low-level interactions and should be reused as often as possible. Components responsible for business logic join together smaller components to build functionalities that execute operations required from the business point of view.A clear distinction between these types of components will allow you to decide whether you need a new component or not. And this drastically reduces the maintenance and modification costs of the web application.
#4 Use TypeScript
JavaScript is a dynamically typed language, which makes it very flexible. However, in React components you do not have strict data types, which makes it more error-prone and makes it more difficult to build new functionalities or maintain existing ones.Therefore, TypeScript is an ideal addition to React-based applications. It can be used in many places, from supporting application API, through app logic, to the smallest UI components. TypeScript ensures the integrity of data types in the entire web application and allows you to avoid type mismatch errors. Additionally, it speeds up the process of implementing modifications in already existing components, pointing out places where type modification is required.
With TypeScript, you can easily use app elements that already exist, supporting IDE (Integrated Development Environment) with additional information. This makes a web app more reliable when implementing new functionalities and reduces maintenance costs and the time needed to implement new features.
#5 Create a common data model for frontend and backend
When implementing new functionalities or modifying existing ones, ensuring consistency between an API and an application is the major portion of the costs. OpenAPI and an automatically generated API interface are very helpful in ensuring the integration of the application frontend and backend without involving developers. In combination with TypeScript, OpenAPI ensures consistency across the application and significantly decreases the cost of API service maintenance.When building a new application, developers have ready-to-use methods and do not have to delve into low-level details of API calls. In the case of more complex functionalities, object-oriented TypeScript and ready-to-use data models from OpenAPI allow you to build intermediary models that make it easier to format data, serialize and deserialize it, or use programming patterns according to the current needs. Such an approach separates the data layer in the application and streamlines the management of the React components.
#6 Use proper communication methods between components
In React, components are organized in a component tree with child and parent components. They communicate with each other in many different ways. The basic communication method is props/callback, the more complex one is React Context, whilst Redux is the most advanced method. In large applications, most frequently a combination of all three methods is used. It is also important where a given method is used. If it is applied incorrectly, it may increase the costs of your React project.“Props” are a set of variables used to pass information down the component tree, from a parent component to a child component. “Callback” functions, on the other hand, are used to propagate information in the opposite direction. “Callback” functions themselves can be also passed down as props from parent to child components. The props/callback method is used to ensure direct communication between parent and child components and to perform simple functionalities.
Bear in mind that communication between components in your React application should not be too complex. If there are many components embedded into each other that send data back and forth whilst communicating, it is difficult to track such data flows. Simpler communication means that you can detect possible threats faster.
React Context is used for communication between components belonging to the same branch in the component tree. Make sure that this branch is not too complex and monitor the performance of such a solution. This method should not be used to build more than one functionality.
The Redux method is used when you need to ensure communication between different components across different levels of the React application. It can be used for many different functionalities and dependencies between them. You need to monitor the number of Redux elements called reducers and split them into smaller, independent groups, if needed.
In Redux, the communication between functionalities should not go through UI elements. It is the user who should be the source of an action and not a component. Also, the HOC technique is very useful when using the Redux communication method.
#7 Use JSS to manage CSS
Using JSS to manage CSS may not be a very elegant solution, but it is a very practical one and works best in most scenarios. It allows you to define reusable styles and generate dynamic styles on the fly.Many ready-to-use solutions are already implemented in JSS. Material UI is one of the most popular ones. It allows you to use many tested and ready-to-use React components and speed up the implementation of simple views. In the case of more advanced views, Material UI offers you off the shelf solutions that can be used as a basis for building your own themes or even components and apply styles to them.
Since JSS is modular, you can limit the number of CSS styles on the webpage to the ones that are requested. This decreases the amount of data transferred. A standard or custom theme makes the work easier, ensuring that frequently used elements are available when applying the styles to the React application.
#8 Use server-side rendering (SSR) while serving your React application
When it comes to application serving, a React web app can be a part of a bigger service and be used only in some of the service’s parts. Alternatively, it can be one small component embedded in a service or be served as a client-side rendered webpage.But most frequently, it is served as a multi-functional information service. In this case, Next or Gatsby are the best solutions. Both Gatsby and Next allow you to have full control over rendering and use server-side rendering (SSR), which speeds up the webpage. But they work differently. If you need to ensure communication between the server and API, choose Next. If you need high performance, Gatsby is a preferred option.