Become one mind with React
It’s important to structure our application in order to keep in mind which part you are working on and what you could do about it. It’s more crucial as long as your codes become bigger and complex. Not having a good structure tends to break/modify old codes and when the time comes you will spend a lot of time just only to restructure your application or codes. It’s painful when at that time because perhaps besides that you need to implement new features and a bad structure will hold you for doing so. So we better design and structure our application first before jump to code.
In my team, I’m involved in the front-end team as a mobile and web engineer. We used React for web and React Native for mobile, so basically both applications are using a React-based framework. Since React is a framework, they already have own architecture and definitely we must follow their rules while developing our application with React. In this article, I’m going to break React architecture to you and how we collaborate with it, enjoy!
Thinking in React
I only provide three parts of React architecture. In reality, there are more you could explore in React such as in programming style aspect or in compilator, but I think I only share with you what the most important things for React developer need to know in order to get a sense about React paradigm.
Composition
It’s the same thing as you do when developing your web in a natural way, means when you build your Element in HTML or in JavaScript we knew it as DOM (Document Object Model). So you compose your all components into a particular tree and let the browser render each component as a tree node, which means the browser will traverse and render your tree node from parent to all node through each node children.
In React it does same thing, you create your component from the top to bottom (top-bottom approach) and let React render all components through the tree and only modify what they need only. Here how complex our web components be composed in React.
Data flow
As you can see, it’s only one direction in the cycle to change your data in React and it’s repeatedly be executed when only and if only there is an action or scheduled task. Let’s see one of example:
export default function CategoryButton({
value = '',
// Other props,
}: CategoryButtonProps) { // Other stuffs
const [currentValue, setCurrentValue] = useState(value);
// Other stuffs return (
// Other components
<Box>
<Click
theme={currentValue === 0? "normal": "invert"}
onClick={() => setCurrentValue(0)}
>
Data Baru
</Click>
<Click
theme={currentValue === 1? "normal": "invert"}
onClick={() => setCurrentValue(1)}
>
Data Investigasi Kontak
</Click>
</Box> // Other components
)
}
This is one of the components in our web, CategoryButton. Note, in order to understand easily what I’m going to say, I don’t provide full source code and modify some of them, so don’t look that component really as real code. Back to the topic, so if we correlate the data flow cycle we see before, in simple words, CategoryButton has these roles:
- View — All implementation inside return (HTML codes)
- Actions — onClick on Click component that calls setCurrentValue to set new value when a particular button is clicked
- State — a currentValue to hold which button should be in concern
When a state is changed React will rerender the view with a new state, but only the part that needs to change. In this context, then only the background and text color will be changed, so it’s not going to modify the entire DOM.
React Life Cycle
Since React 16.8, there are a lot of changes happens, including the way we treat React Life Cycle. Let’s see React Life Cycle when we use a class instead of function!
In my opinion, this is a complex life cycle but it has more freedom to do anything you want. For example, componentDidMount is called only once time at initialization and componentDidUpdate will be called after any state update. If you look again the image, you can see componentDidMount and componentDidUpdate actually exist in same phase, where it comes after render. For your information, most cases, these two function usually has the same implementation. But in minor cases, actually, it could have a different implementation, so having this life cycle is good since you could separate functionality with the same phase but different cycle time.
React hooks still has the same life cycle phases, but not all phases are defined explicitly like we did in class. For instance, you know in class we could have componentDidMount and componentDidUpdate, in React hooks we are no longer to have those separated functions, but only one that is useEffect. useEffect will do anything after each renders regardless of which cycle the component right now, so it’s quietly the same as componentDidUpdate but including initialization cycle.
In fact, we could trick useEffect to behave like componentDidMount and componentDidUpdate by having a boolean state that indicates it’s the first cycle or not. So set the state to true for the default value and after it renders at once then set it to false.
My point about this section, React life cycle is never changed and still the same as right now but it has a different way to treat that in Hooks. There is no problem at all to know how React life cycle works in class even though you always work with Hooks. Certainly, you will gain more insight and do better to treat the React life cycle in hooks.
How we extend the capability of React
There are some problems we were facing in React, such as how we show a modal or call alert from different pages. Since we want to follow DRY rules, so we couldn’t create the same modal or same alert component for each page. We know that React uses composition on their architecture and we take this as a benefit to tackle that problem.
Basically, what we do only create those components on the parent component and share it to all its successors. In our case, it will be placed in the root component (App.tsx), so it’s accessible by all components. Let’s see the comparison of flow between with or without this architecture.
So every successor of App could use Alert and Modal without copy-paste the same component for a new page that needs it. In React we could achieve this by context, you can get insight more about this in my other blog about working in React deep down in here. Note, this approach is actually the same thing as we define a global state, so not only modal or alert but we could generalize this problem into anything like you could share theme for styling to all components.
Takeaways
This article is made based on my experience when working in React with my team. In reality, by understanding all these parts, I feel my works are more controllable and know what should/shouldn’t do in some part of codes in React, I feel like I’m not afraid to break any rules when implementing a new feature because there is no such thing I need to break and still follow some principles in programming, so it’s a lot of benefits in programming perspective. In conclusion, having a good architecture will bring you to have a maintainable and scalable application. I hope you could get my all points from this article and you could do more better than me in your project or work. Thank you!