React Architecture Best Practices and Tips from Community Experts
Table of Contents
- What exactly is React architecture, and how it helps in web development?
- Steps to implement scalable React architecture pattern
- React Architecture Diagram for building large Web Applications
- React Architecture Best Practices (Contributed by 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.
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 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 use in real-world applications. That’s where state management libraries like Redux come into play.
In the next sections, we will discuss how to implement a scalable React architecture with best practices.
Ready for the ride?
Steps to implement scalable React architecture pattern
Laying the foundation of a scalable architecture in large applications is not as easy as it seems. You could either end up going south or things may not work out as planned.
Even worse, there can be times when you need to reinvent the wheel only to find out you’re still stuck in the middle of nowhere.
Heavy stuff, ain’t it? The uncertainty of React architecture, attached below, is a comic strip that sarcastically depicts how painful implementing a React architecture in large applications can be, at times.
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?
- How to decompose your application UI into components?
- How to Implement data fetching with Redux?
Let’s take a look at how we approach these questions and design a scalable React architecture for large web applications.
React Performance - 13 Ways to Optimize Performance of your React App
How to design a loosely-coupled React architecture?
Here’s the thing about React that helps in web application development: the promise of a loosely coupled architecture.
The term – loosely coupled architecture – signifies an architecture in which each component has little knowledge of other components. In other words, it’s a system in which each component is independent and reusable throughout the application.
Ideally, you would want your architecture’s components to be loosely coupled as well as highly cohesive so that you can easily maintain a web application when it grows.
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 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 codebase with modules, each with its own responsibility. The idea is to break down your application into smaller, single-purpose components. It is, in my own opinion, the best solution to build large-scale web applications.
Moving forward, let’s check out a step-by-step breakdown of the React architecture diagram and see how it works:
Remember we talked about components being the structural units of an architecture? In general, we’d like to group our components in modules (See image below).
Next, the state of some modules usually splits from the components and moves into the Data Store.
The reason why we are using state management tools like Redux in our architecture is to track and react to the change in the state of the components. That’s where events come into action.
For instance, let’s assume we are building a web page for a Single Page Application (SPA)– Proctors where doctors register themselves and interact with the patients.
Suppose, a doctor enters a username that doesn’t meet the profile creation criteria, the required field would trigger an event that reads “username is too short”. This results in the change in the state of the component.
As soon as Redux detects the change in component state, a special render function will be called on the component.
That’s when React does the trick. As soon as the component is ready to be rendered by the UI, a virtual snapshot of the change in component state is taken. React now compares the snapshot with the real DOM and analyzes the differences. Once it finds the difference, the changes are applied to the UI that’s reflected on the user’s screen.
What’s more, the overall process of component rendering is so fast that sometimes it affects the performance of the application. We have already covered an in-depth explanation of Virtual DOM and how it affects the React performance.
Note how each element in the Reactjs architecture diagram is loosely coupled from one another. That’s the thing about React architecture!
Here’s our wireframe that resembles how our registration data would look like when a doctor’s registration is successful:
Now that we know about the data, the next step would be to breakdown our application UI into components.
React Architecture: 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 component with tons of states and side-effects. A total disaster we would say. Here are some consequences if you write your React application as a single component:
- The poor performance of UI – Since the application has a single component, each change in state would result in the re-rendering of components. As a result, performance would suffer drastically.
- No code reusability – Code reusability would be a thing of the past, for we just have a single component there.
- Poor testability – In this case, you only have integration testing at your disposal. However, that alone won’t be sufficient for your application to perform well.
- Lack of team collaboration– Needless to say, if you are working on a single component, it’s going to be a tough task to work as a team.
Well, these are enough reasons. So, let’s break our UI into multiple main components.
Isn’t this supposed to make our work simpler than before?
Let’s see how the component diagram looks like:
Note that how we divided the root component <Doctor> into several independent components such as <DoctorDetail>, </Sidebar>, and <footer>.
Now the question is: if our UI is structured this way, how would the data fetching process look like?
Reactjs Architecture: 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 kind of 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.
Now, let’s assume that <Doctor> is our outermost container component that is near the Redux store. So every time any component needs data, it’s the <Doctor> components that will serve as the single source of truth and help them with data.
For instance, if the <img> component of the webpage needs data, it needs to be passed via <Doctor> to <DoctorInfo> to <title> and finally to <img> component.
But… What if some components in the hierarchy don’t need the data at all?
Well, you can plug in the data into any component without affecting the other components by using a library called React-redux.
After the data is passed on to other components, the change in the state is passed on to reducers that update the UI.
Take a look at how a complete React architecture diagram looks with Redux:
React Architecture Diagram for building large Web Applications
The doctor’s application example that I mentioned above is the simplest use case for representing React application architecture.
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 our Proctors 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.
React Architecture Best Practices (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 folder 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.
We reached out to several Reactjs experts and contributors to find out the practices they follow to scale large web applications. Here’s what they shared with us:
#1: Don’t overthink the application structure and 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 when your application grows
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 container component 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 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 when your components grow in numbers
Did you know Facebook’s codebase consists of over 30,000+ React components?
When you are working on a large, scalable React project, you’ll witness a surge in the number of components.
Phillipp Spiess, Front End Engineer at Facebook, opines to stick to meaningful component names to make codebase searches effortless for your developers.
#4. Divide your features into separate reducers, with each one exporting its own action creators and selectors
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 and side-effects in your codebase
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 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 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.
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 tips and 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.