React Dedicated! Design Pattern
Well, I believe react is one of the most used JS library in the industry right now. It is being used to build user interfaces for mobile and web devices. After several months of reading, course, and do some projects (including the one we’re currently doing for our software engineering project), there be surfaced some common design patterns. 🔥
Well in general, what is it?
Here, I’m going to tell you what a design pattern is.
Design patterns are typical solutions to common problems in software design. Each pattern is like a blueprint that you can customize to solve a particular design problem in your code 👩💻
It is made to solve a challenge, for example, I want to create something that is like “bla bla bla”, well, you’re not the only one who encounters this challenge and someone has once created this bla bla bla, even though the details are a bit different, but I want to implement something that is similar to that one guy who made the bla bla bla earlier. 🧯
Turns out, many people wanted to do bla bla bla, then, a design pattern will soon emerge out of all of the similarities. 🍁
So, it’s basically like a toolkit, a premade solution to common problems in software design. It’s been used so many times with different use cases by different users, that it turns into a “terms” in the design language. So when you said “Singleton Pattern”, or Factory Pattern, developers will understand what kind of system you’re making. 😊
Well, I must tell you something before you’re misunderstand me 😁. Design pattern isn’t a stack overflow to go tool. It isn’t something you can copy paste, like libraries or modules, functions. It’s now a specific code, but a general concept or idea on how to solve something. The details must be suited and adjusted for each problem. 👻
Sometimes, people confuse algorithm and design pattern.
- Algorithm defines a clear set of actions to achieve a goal.
- A pattern is a high level description of a solution. The code of the same pattern applied to two different product can sometimes differ very much in implementation,
There are four things building this design pattern:
- Intent describes briefly both the problem that wanted to be solved, and the pattern solution that can be used for that problem..
- Motivation, explains more on how to implement it and how to problems can be solved utilizing a certain design pattern
- Structure of classes shows the components of the pattern, what things are needed, and how to build those.
- Code example, the code example or use case where it can be used.
Who Found America?
Asking who found America is similar to asking on who first made this design pattern concept which basically already been used but just doesn’t have name. A pattern is discovered by the community. When it’s being used over and over, it will come to live by itself. 🍀
So basically design pattern is more of like a design solution which passes the test of time. The concept of design pattern itself was first described by Christopher Alexander. Many books followed, and voila.
They’re Speaking The Language of __
Design pattens are tries, tested solutions. Even when we never encounter a certain problem, learning it will totally be useful, because it teaches you to solve problems using principles. 🥰
Because it’s not an exact thing, you might discover yourself a solution that is inspired by it.
Well, design pattern can also be said to be a common language for a developer team to communicate. This kind of conversation sometimes happens in my current team:
Oh does this zustand act globally as a singleton?
Can’t we just use the HOC pattern for this component?
No need to explain further those terms because it’s a common language and everyone should know it already.
The problems with it
- Sometimes it’s overused. A problem that doesn’t need a design pattern to solve can be overly solved with design pattern, and sometimes can be unjustified. 😭
- Different programming language have different feature. In a certain programming language, function as an object is not possible. So patterns that are based on passing function as a parameter might not be able to be implemented. 🌵
- The previous thing I mention can actually lead to a bad practice of a certain programming language, for example, if you insist java OOP style on React project, it would be horrendous. 😐 React has its own dedicated design pattern and Java also has its own dedicated ones. Using it interchangibly sometimes can worsen performance, and make it unintuitive for those who are familiar and work long enough in a certain project.
Classification of patterns
Design patterns can be categorized by their complexity, level of detail, scale.
The most basic and low-level patterns are often called idioms. They usually apply only to a single programming language.
But there are high level patterns, that are called architectural, it can be used across several programming languages. In addition, all patterns can be categorized by their intent, or purpose, those are:
- Creational, (Object and model creations) 🤖 We will rarely use this in React
- Structural (Assemble objects and classes into larger structures) 🏢
- Behavioral (Effective communication, assignment responsibility) 🐰
(But this isn’t necessarily important in React design patterns though, because they’re mostly functional and not OO)
Now, let’s talk about the patterns of react.
1. Presentational and Cointainer Component Pattern
In this pattern, we should divide components into reusable components and its container. This is one of the most used pattern to achieve the design principle, the separation of concerns and components reusability
- Presentation components, These are the components that are responsible for how the UI looks. They don’t have any data dependency, and only used to display data.
- Container components, it’s responsible more on how things work, it grabs the data needed and uses the presentation components to show the data.
In our software engineering project, I used this once in the Coin details screen.
In this coin details screen (this is called the Cointainer Components, take a look at line 58. It will call another components. This is called the Presentation Components).
Here The TimeButtonContainer takes all the props and will show the button. Here I used nested components because I provided another abstraction for the button so I can reuse it.
The usecase is actually a bit unique and not intensely used. For example, a component that rely heavily on data fetching sometimes unseparable. This design pattern is not necessarily be remembered. Sometimes you know when to use this by intuition.
2. Provider Pattern
Sometimes there are props that have to be acquired in a certain place of your components, but passing all of them can be quite nasty. This is called the prop drilling problem 🛠.
Prop dilling is a scenario where a prop is passed into the components too far from its usage.
Let’s denote the blue dotted node is where the same prop is being used. Their lowest common ancestor is the root. Too pass this information, you should pass them through the roots, to all those other components that doesn’t even need that prop.
Imagine the tree is so big, this can be solved with the provider pattern. Provider pattern allows us to store data in a central location. Can be said this is similar to a singleton storage that can be used towards all of your components. Furthermore, you can use a hook to take the props you wanted.
This way. It will reduce the unrelated components that takes a certain prop as their parameter.
For an example:
There is a coininvestment card components, basically in line 62, we used the provider pattern, which will return the function that takes a coin id as parameter, and will return the amount of coin a certain user currently have.
This is what it looks like, so, rather than having the invesment and the screen itself holds this getInvestment
method, we can just use a provider hook to separate it.
In other case, if for example the header actually needed the getInvestment
method as well, we can easily use the same provider hook to obtain the method.
Here we use Zustand by the way 🤣.
3. Asynchronous Use Effect Pattern
(Lmao I discovered this one and have been using it throughout the place it might be a bad practice but if it works, it works)
Sometimes in a component, you have to get a value from the provider and call it asynchronously within a use effect. To do it, you should create a nested function inside the use effect, and call it.
Look at line 50. Here, I have to call the asynchronous getTotalInvestment
method. To do it, I can pass in a none asynchronous useEffect callback, provide an async function, and call the async function without await in the useEffect.
This way, I wrap the asynchronous function with a wrapper.
I think I found this pattern some stackoverflow. Which has the best answer and some upvotes.
4. Functional Component + Hooks Patterns
Now, for the extra part, other than design pattens, I think I should add this into the pattern. This is just me being smart-ass. But React > 16.8 has a feature called hooks, which was introduced to change class components into functional components.
A little bit of a background check. I’ve always been using the functional version of React, and never have I once code using the class component version of React. So, I don’t really understand the point at first, but now I begin to understand.
So, I think people should learn about this when they get into react at first.
It’s not really a broken change as both of them can be used interchangably, I think hooks are just a syntatic sugar to class based functions.
So functional components actually like a function. They are called with a component, and they will return something.
Little bit different with a class, they can have property, and a certain method inside that class can change depending on the state as what react devs refers too.
Now, Hooks are functions used with functional components that let us hook into a react state, and perform this state changing mechanism.
By convention, hook uses the prefix use
. Hooks area created inside the functional component which will be called every render, But hooks are impure functions, it's implementation inside react basically check whether the component has mounted before or not, if not, it will set it to the default value and so on.
Check this out, when using functional components, the code will be like this
import React, { useState, useEffect } from "react";
import Input from "./input";
export default function Greeting(props) {
const [first, setFirst] = useState("Harry");
const [last, setLast] = useState("Potter");
useEffect(() => {
document.title = `${first} ${last}`;
console.log(document.title);
}, [first, last]);
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
let handleResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, [width]);
return (
<>
First <Input value={first} onChange={setFirst} />
Last <Input value={last} onChange={setLast} />
<hr />
Width {width}
</>
);
}
Let’s compare it when we use class components:
import React from "react";
import Input from "./input";
export default class Greeting extends React.Component {
state = {
first: "Harry",
last: "Potter",
width: window.innerWidth
};
componentDidMount() {
window.addEventListener("resize", this.handleResize);
document.title = `${this.state.first} ${this.state.last}`;
console.log(document.title);
}
componentDidUpdate() {
document.title = `${this.state.first} ${this.state.last}`;
console.log(document.title);
}
componentWillUnmount() {
window.removeEventListener("resize", this.handleResize);
}
handleFirstChange = first => {
this.setState({ first });
};
handleLastChange = last => {
this.setState({ last });
};
handleResize = () => {
this.setState({ width: window.innerWidth });
};
render() {
const { first, last, width } = this.state;
return (
<>
First <Input value={first} onChange={this.handleFirstChange} />
Last <Input value={last} onChange={this.handleLastChange} />
<hr />
Width {width}
</>
);
}
}
Yes, they did the same thing but their implementation is different.
It’s really cool!
I wanna say that react patterns are a lot more than just that four. But those I wrote are one of the basics one which I use in my software engineering project mostly!
So, that’s all from me. I wish you learn a lot lot lot lot lot from this post! c ya
References: