When we talk about web development React.js is often an topic that appears in most of conversation but what is it?
React.js or React is javascript framework used to build the front of web applications.
Instead of the usual front-end project, React.js is not based on the organization of the HTML and CSS in the same file but it strongly relies on object paradigm.
In React, the structure is composed of components which are the equivalent of objects in the Java programming language.
However, at the difference of Java, all components need to extend from a common parent component and implement the render function.
This render function is the function that returns what will decide how the component will be seen in the HTML document and it is the equivalent of the function toString in Scala but as we are in a front-end framework, all objects are obliged to implement this function because the output of the code will be a mix of HTML, CSS, and Javascript.
Another big difference is that in React.js changing one variable in the object will recreate all objects and it will lose its current values.
To bypass this problem, React.js has something called the state which is a sort of memory that can change without recreating all objects. That’s why all variables subject to change often are putted there.
The last big difference between Java and React.js is that for React information always go down in the component hierarchy but without any trick to change the flow direction, it never goes up. Due to this some patterns and libraries are particular to React.
So as every framework React.js comes with its good practices and conventions, I will present you some of the patterns designs which are the keys to understand the structure of the application:
- The first one is the container, a design pattern to split logic from the application from the layout of the content.
- The second one I want to present is Redux, a library to make information go upper in the component hierarchy.
- The third one is Saga, a library to create asynchronous code easier.
- The fourth one is React router, a library to centralize requests.
The first pattern I want to explain is about containers and presenters.
The principle of containers is to split visualization and API requests into two different components but this pattern also allows us to split big component into smaller ones and the schema of its operation is just below.
To make a clean break between view and data, the component that process some data from API or store them need to not be linked with the layout and the one in interaction with the view need to be stateless or without memory.
This structure permits us to have a highly adaptive component for a low complexity because all the processes are centralized in the container and presenter are small and only here for layout. Due to that, a change in the layout will not affect all the view but only the presenter concerned.
Even if this pattern is simple I was wanting to explain it because it is used in nearly every page of the application so it is important to understand it well. If the notions saw in this part seems too abstract, the first appendix can provide you a real example with a page from the application.
The second pattern I want to introduce is Redux.
As the information always goes down in the hierarchy, we need tricks to make it go higher.
The easiest way is to use a callback function that is defined is the parent component who needs the information.
When we do not have a lot of information to pass this method can be a good solution. However when we have more information to pass, we need another method. Otherwise, the application will become complex. Because of this library, Redux, have been created to make this kind of communication easier.
Redux is based on three elements:
- The actions which are basic functions that uniformize data and set a variable to choose the path.
- The reducer is a router between possible paths.
- The dispatcher is the element that calls reducers.
These 3 elements are organized as in this schema.
When a component wants to do an action it calls the action function corresponding to the action we want to do. Then this action is received by the dispatcher which sends it back to every reducer that is registered. When the information goes in the reducer it activates the proper code that returns an output to the component by changing information linked to it.
What makes reducers so powerful is that they are common to every object in the application.
Because of this, they allow all the object linked to it to have information in common. This trick allows us to make information go higher in the hierarchy with a really clean and low complexity solution. This is why in most of the projects this solution is chosen.
The third pattern I wanted to present is Saga.
Asynchronous code has always been a pain to write and source of bugs.
This is mainly since our brains are used to think linear that’s why a library, Saga, have been created to write asynchronous code as it was linear.
This library is based on a pattern from the same name so I will start by explaining this pattern to present this library.
The saga pattern is here to propose an easy way to use asynchronous code without blocking the main code by using event and it is implemented in React as we can see on this schema.
In this pattern, all of the asynchronous function is triggered by an event and finish by triggering another event.
This allows the asynchronous code to be detached from the rest of the code and even to hide the asynchronous nature of the function.
In the library, asynchronous code is done with generators and events are done with the actions of Redux to make the implementation easier.
Due to this, write asynchronous code becomes a way easier, it transforms asynchronous code into writing only a couple of actions and generators function which are linear. This is why we choose to use this solution in the application.
The last pattern I want to introduce is the front controller.
In an application, enter points are really important and are often written with the same code.
To prevent this repetition of code, a pattern called Front controller has become a classic in any web application and is organized as we can see on the schema below.
Its structure is quite simple and dependent on these entities:
- The handler that will redirect every request to the good controller.
- The front controller itself that will treat the request and give it to the handler.
As you can see, this pattern is not complicated but it has a big inconvenient which is that the handler will depend on every controller but as the handler is an unstable class it is not a real problem.
In React, a library based on this component has been created and its name is React router and as the front controller is near an obligation in web development we were obliged to use it because it is the best way to organize the transition between pages.
Now that we saw all the required notions to understand the structure of a application. I will now start to present its structure and details the reasons behind it.
Let's start with the explanation of the usual structure that looks like the schema below.
As you can see every pattern we talked about before is here.
The page is, in fact, a container that is in charge to communicate with the API via Saga and to keep the information in memory by its state and Redux.
We use Saga to communicate with the API because the communication needs to be asynchronous code to not block all the application while we are loading resources of the page.
Then inside it, there are a lot of small presenters which are in charge of the layout of a part of the page. These presenters are stateless and communicate with the intermediate of callbacks that allow then to make information go up in the component hierarchy.
Finally, the page is called by the router which is, in fact, the handler from the front controller.
Here we can see the actual utility of the router in React because without it each page would be a dependence for other pages that point on it. That would make all pages depend on each other and it would be a great trouble to maintain.