React Architecture Best Practices and Tips from Community Experts
We’ve had a few clients who’ve wanted to migrate their legacy application to a new frontend like Reactjs. Upon interacting with them, we figured out that a few of them didn’t know what an application architecture is. And even if they knew about it, they didn’t care about asking their agency or developer about it.
Here’s the thing: like most things in life, taking time to plan ahead and invest in a scalable architecture can help in the longer run, especially when your web application is going to serve a large number of users. This is when understanding some of the architectural considerations and tradeoffs behind building big websites can result in smarter business decisions. If you’re determined to invest in a scalable react architecture for your website, Simform’s custom web app development offering is for you.
Here’s a graph that illustrates the difference in growth when you invest in architecture vs when you don’t invest in architecture at all:
The green linear impression says it all, doesn’t it? Ergo, investing in a scalable architecture from the get-go can benefit your business in the longer run. Now let’s see:
What exactly is React architecture, and how it helps in web development?
Unlike other UI libraries and frameworks, Reactjs doesn’t enforce an architecture pattern. It is just a view that caters to the user interface.
Just beneath the user interface lies a tree of several React components. In general terms, a react component is nothing but the central structural unit — something minimal, like a button, label, or text input label or perhaps something more complex, like a registration form, user-profile, etc.
Now here comes the exciting part: all higher-order components in React may hold a state; however, it’s not mandatory. By state, we mean the data needed to track for making the application work. Also, your application state keeps on changing from time to time, depending on the action taken by your user. It’s only the state of data that determines what displays on the UI of an application.
React already offers an out-of-the-box mechanism called the local state. However, the mechanism is not sufficient alone to be used in real-world applications. That’s where state management libraries like Redux come into play.
In the next section, we will focus on some of React architecture best practices for implementing it in our projects. Ready for the ride?
React Performance - 13 Ways to Optimize Performance of your React App
React architecture best practices
#1. Navigate a directory structure
Folder helps you to craft a hierarchy within the project management software so that developers can find whatever they’re looking for. The most important advantage of this folder structure is developers cab can grasp all the files that belong to a feature at once. Plus, it’s easier to maintain the code and reuse it as per their needs.
Here’s an example:
A typical React project has a source (src) folder where all the files and folders get listed, as shown below. The focus should also be on component-centric file structure:
└── /src
├── /assets
├── /components
├── /views
├── /services
├── /utils
├── /hooks
├── /store
└── App.js
├── index.js
├── index.css
- The asset folder comprises the project’s static files, such as your logo, fonts, images, favicons, etc.
- The component folder comprises UI codes such as buttons, forms, avatars, etc.
- The views folder contains all the web pages.
- The services folder comprises code that helps you to communicate with external APIs.
- The utils folder contains reusable function snippets.
- The hooks folder comprises reusable code and new component logic.
- The store folder contains state management files such as Redux.
- App.js comprises the main or regular component of your application.
- Index.js is the entry point for any React application.
- Index.css is the global sheet for styled components in an application.
#2. Focus on common modules
React is a non-opinionated framework, which means it doesn’t enforce a particular way of structuring your code. Therefore, you can divide your modules however you want while building a React application. React framework will assist you in reducing the development complexity and creating open, reusable, and shared structures.
For that purpose, you should focus on common modules such as reusable custom components, custom react hooks, business logic, constants, utility functions, etc. You can use these modules right through the software in various components, views, and projects.
#3. Add custom components in folders
Components are independent pieces of functionality that you can reuse in your application, and are the building blocks of all React applications. Adding custom components in folders helps keep projects organized and easier to navigate. It separates standard components from custom components, making them reusable, accessible, and maintainable, and enhancing scalability.
Let’s take an example of a React custom input component. In the component directory, create a new folder named “Input.” Within this nested folder, all the files as shown below:
└── /src
├── /components
| ├── /Input
| | ├── Input.js
| | ├── Input.css
| | ├── Input.test.js
- Input.js comprises all the logic of the custom component.
- Input.css contains the styled-comonents part.
- Input.test.js comprises all the test cases.
Now, create an index file named Index.js inside the pure components directory as shown below:
// /src/components/index.js
import { Button } from './Button/Button';
import { Input } from './Input/Input';
import { Card } from './Card/Card';
export { Button, Card, Input };
After setting up this file, you can use this custom component throughout the entire project architecture.
#4. Create custom hooks
A custom hook is a function that starts with “use” and may invoke other Hooks. It helps you to reduce code complexity. Suppose you have two different web pages called Login and Registration. Both of these pages will have input fields where visitors will enter the required information, and click the submit button at the end.
Now, if you want the password toggling feature for both these pages, you must write the same code twice. That’s where the role of the custom hook comes into the picture. You can create a custom hook for password toggling, as shown below:
└── /src
├── /hooks
├──usePasswordToggler.js
In the usePasswordToggler.js file, you can define the logic for password toggling and save it in the single folder. After that, you can use this custom hook in your React app source code whenever possible. You don’t need to write duplicate code for the Login and Registration pages. Custom hooks help to reduce code complexity and enforce reusability.
#5. Use absolute imports
By default, React application comprises plenty of nested structures, which may lead to confusion when importing any element.
// some file
import { Button } from '../../components';
You can avoid such confusion by adding support for importing modules using absolute paths. For this purpose, you can add a rule to the jsconfig.json file at the root of your project. A jsconfig.json file helps your editor’s Language Server Protocol to comprehend JavaScript or JSX (A JavaScript Extension).
Here’s an example of how jsconfig.json can help:
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src"]
}
With a rule added to the jsconfig.json file, you can import components located at /src/components with the following coding snippet:
import { Button } from 'components';
#6. Avoid a single context for everything
One of the most common problems in a React application is figuring out how to share the current state across multiple components. The complexity can multi-fold when several components exist between a parent and child component, requiring the passing of render props between them.
React Context is essential for transmitting data via component tree without restoring to default prop drilling. It means a parent component can pass on the props to all the child components beneath. Using multiple contexts in your React application can help you avoid a single point of failure and accomplish various tasks effectively.
#7. Separate business logic from UI
To enhance the quality of your source code and make software maintenance a breeze, you should separate business logic from UI. The main component i.e., UI should get stored in the /pages or /views directory. Building custom hooks can help you to solve this problem. You can also use the React Query library, a custom hook that helps you to fetch, catch and update the content.
#8. Use the utils directory
The utils directory comprises some helper functions that you can use right through your React application. It’s not compulsory to utilize the utils directory. However, it’s recommended as it assists in maintaining a clean code and enhancing software quality.
So far, we have gone through the nitty-gritty of best practices and folder/structure changes that can help you to create a scalable web application. However, the question still remains-how to create one/what are the steps involved? Let us find out in our next section.
Steps to implement scalable React architecture pattern
When writing a React application, our development team at Simform regularly contemplates the answers to these questions:
How to design a loosely-coupled React architecture?
Rebecca Murphey, Author of jQuery Fundamentals, puts it succinctly as to why you would probably don’t want your application components to be tightly coupled:
One of the major challenges faced while dealing with complex codebases is the involvement of a massive team of front-end developers. Worse still, it can go to a point when they start spending a major chunk of time figuring out what the code does instead of actually writing it.
One way to counter such a challenge is to structure your entire codebase with modules, each with its own responsibility. The idea is to break down your application into smaller, single-purpose separate components. It is, in my own opinion, the best solution to build large-scale web applications. You can also take advantage of microservices for this purpose.
How to decompose your application UI into components?
Did you know that a React application can also be written as a single component? Why yes, it can! Reactjs lets you do that but it’d just be overkill if we do that.
The result would be a single giant functional component model with tons of states and side-effects. A total disaster we would say.
Here are the two major techniques that we follow:
1. Split the render() method:
A common way to split the render() method is to create additional “sub-render” methods on the same class. However, for detailed decomposition with reduced complexity, you can use functional components.
2. Templatize components by passing React elements as props
If a component is too complex due to multiple variations or configurations, convert that huge component to a simple template by using React’s ability to pass elements to create a flexible template component.
How to Implement data fetching with Redux?
First off, we need to fetch all the data from a cloud-based server and put it somewhere. Next, the data actually needs to be displayed. It’s important we assign pieces of this data to corresponding UI elements that represent what we see in the browser.
Finally, we need to handle changes to the data. For example, if a user marks any doctor as a favorite, we need to update the HTML accordingly.
Although Reactjs possesses built-in classes to store such a change in data, it’s not easy to use them when the application is large, let alone complex in nature. That’s why it’s wiser to use Redux in such cases.
With Redux, we fetch data once and store it in the Redux store that can be used as a Single Source of Truth. This means it is now all ready to be used anytime by any component.
Take a look at how a complete React architecture diagram looks with Redux:
React Architecture Diagram for building large Web Applications
In the case of a large React application, it’s not easy to plan each and every component beforehand as there would be thousands of them. Even worse, if your components end up becoming large then handling state with Redux would be difficult.
So..what are the possible ingredients for a scalable React application architecture, you ask?
Speaking of a typical web application example, here’s how a React architecture diagram should look like:
This should be the magic sauce for building large React apps. The architecture uses React libraries like Immutable.js, Redux-saga, and Redux that are hailed as the first choice of developers for building web apps.
Here’s why the architecture is suitable for building large react apps:
- Consistent global state – Since we now have one store to contain the app’s state, a change to that state will automatically update all views.
- Better scalability – When used with a scalable backend like Nodejs, this architecture can scale well and meet the needs of business expansion.
- Better testability – Since all the components and features are independent, testing in between sprints is an advantage from the get-go.
- Decoupled components – The architecture use Redux-saga to tie decoupled components together and to support asynchronous flow for better testability.
With React architecture known to you, you would be in a better position to implement the best practices as you know each component in detail. So, taking that into consideration, we’ll explore some of the additional tips suggested by the Reactjs community experts in the upcoming section. These are more practical solutions they implemented in their projects.
Additional Tips to Implement React Architecture (Contributed by experts)
We can’t stress enough the importance of best practices in building scalable architecture patterns for large applications. From using the best code quality standards to organizing the fReact older structure for different teams, there are no limitations to what your best practices could be like.
For some developers, giving meaningful names to your files could be the best practice, whereas, for others, it could be as simple as using the best libraries that optimize the workflow. Putting that into perspective, we reached out to several Reactjs experts and contributors to find out the tips they follow to scale large web applications. Here are additional tips contributed by the Reatcjs experts::
#1: Avoid using too many nested files and folders
When it comes to the folder structure, we feel Reactjs is very opinionated and gives you a lot of freedom to think and experiment. There’s no default way of managing the folder of your React application.
Jack Franklin, a renowned Reactjs developer, expressed his views when we asked him about important constituents of a scalable React architecture:
He further shared his favorite pattern to structure Reactjs applications:
#2. Stick with a structure that binds your whole team together
Dan Abramov, the creator of Redux and a renowned React developer, suggests:
“Move files around until it feels right!”
When you have a team of developers working on the same project, moving files here and there isn’t something you can afford. This is why it becomes imperative to stick to a folder structure that would eventually help your team stay organized as your application grows.
For instance, traditionally a React application follows a folder structure like actions/, components/, containers/, etc. Let’s say you want to add a presentational and container components NavBar, here’s how the folder structure would look like:
While this structure can work for small independent React projects, it by no means is suitable for large applications.
To solve this, you can group your files by feature instead of type. Let’s give you a peek into the new folder structure with this format:
In a nutshell, the developers working on this project structure would only need to navigate to a single folder to work on something. A single feature for a single purpose makes for a no-nonsense structure. The result? Your teammates would thank you, for they’d find it easier to replace and find files.
#3. Be mindful about naming conventions
Did you know Facebook’s codebase consists of over 30,000+ React components?
When you are working on a large component-based, scalable React project, you’ll witness a surge in the number of component file.
Phillipp Spiess, Front End Engineer at Facebook, opines to stick to meaningful component names to make codebase searches effortless for your developers.
Phillip says:
#4. Divide your features into separate reducers
Another best-practice of implementing React architecture in large-scale web applications should be related to Redux and how to use it in large applications. This Javascript library is a cool tool for a variety of applications. However, there might be some situations where you might not need it at all.
Maintaining Redux integrations in large-scale applications requires a more sophisticated approach that scales better.
Alex Moldovan, an Open-source Engineer at @teleporthq, suggests using a feature-based approach to counter scalability related challenges.
Since every feature has a dedicated folder, the teams can work on them more effectively. It is recommended to modularize the structure in a way that the Redux data (actions, action types, and reducers) can be self-contained. A small step before doing this would involve dividing your application features into different reducers. So even if you want to remove or redo an entire feature, you can simply delete the entire folder that contains the data.
#5. Use Redux-saga to handle a lot of asynchronous code
Let’s accept it: handling a side-effect in development is a big challenge. Side-effects, such as an async API call, storage interaction, or interference by DOM event handler, make your React code hard-to-test, unreliable, and sometimes hacky. They make it even harder to add stability and certitude to the application you are striving to build. Especially, in Redux-based React architecture, you need a nice way to handle those side effects so that it don’t break the view-layer or the predictability of your store.
In Reactjs – you have redux-thunk to handle such side-effects, but it’s more suitable for small and internal projects. Ion-Alexandru Secara, a software developer at Loopup, recommends using Redux-saga to control side-effects and make asynchronous processes (fetching data, sending requests etc.) easier to control and testable.
Final words
We live in a technological era that moves fast, and this is especially true when you are to compete with the competitors in your business. Maybe you need to launch a new product or release a new feature, it is inevitable that the demands from your users and internal stakeholders will keep growing. Here’s why it is important to build your product with a scalable architecture pattern.
As the principles for React architecture defines, always keep looking for React best practices to refine, simplify, and improve the architecture of your web application. In this article, we discussed a scalable architecture pattern and some best practices for building react web applications.
Need help in building a scalable React architecture for a large web application project? Hire remote reactjs developers from Simform to build and scale your web application projects.
Jimi
Nicely done! Definitely Helpful!
Jitendra
Nice and Helpful
Ratnesh Shukla
This is very nice blog well written and define you experience about React Architecture and best practices. Thank you it will help me a lot...! Keep it up :-)
GAURANGKUMAR SHAH
Nice Article
Brajesh Goswami
Awesome article!! Great work.
Anonymous
thanks !! helped alot
Marcos
Useful advice, thanks for sharing this informations :)
Tarun
Many things has been mention in this single post. Thanks for sharing useful information