SOLID implements in React Project

Introduction

SOLID is a popular kind of design principles that are used in object oriented programming. SOILD can not only be used in backend which is just like jave or nodejs, but also be used in frontend. We use those principles to design our component and function, to make our codes and business logic cleaner and better for readability, easier to scaled and maintained.

So what's the concrete means of SOLID priciples?

SOILD stands for five key design priciples, we should code with conforming each of those. Though. sometimes some of these principles may look similar but they are not targeting the same objective.

Explain SOLID

S (Single Responsibility Priciple)

A class should have a single responsibility, such as User class, Log class and so on...

If a class has many responsibilties, it increasees the possibility of bugs and the complexity of code maintenance, because changing one of its responsibilities could affect the other ones unexpectedly.

This principle attempt to separate behaviours so that if exceptions arouse by changing, it won't influence other irrelevant behaviours.

O (Open-Closed Principle)

Class should be open for extension, but closed for modification

In jave. we typically create a new class by inheriting existing class to implement other diffrent functionalities instead of modifying directly

Make it simple, if we want a Class to peform more functions, the informed approach is to add the functions that already exist, instead of changing them.

This principle aims to extend a Class's behavior without changing the existing behavior of that Class. This is to avoid bugs wherever the Class is used.

L (Liskov Substitution Principle)

The object of Child Class can replace the object of its base Class.

That can cause bugs When a clild Class can't perform the same actions as it's parent Class. It's a child Class that should be able to do everything which it's parent Class can do.

This principle aims to enforce consistency so that the parent Class or its child Class can be used in the same way without any error.

I (Interface Isolation Priciple)

使用多个专门的接口比使用单一总接口要好 Clients should not depend on methods that they do not use at all.

It's wasteful when a Class is required to perform useless actions. that may cause unexpected bugs.

This principle aims to split a set of actions into some smaller sets so that only executing when it is required

D (Dependency Inversion Priciple)

High level modules should not depend on low level ones. Both should depend on abstraction. Abstractions should not depend on details, details should depend on Abstractions. It's a little difficult to understand it.

In a nutshell,we should programe oriented interface. Abstracting into a interface makes the implementation of each class independed of each other and loose coupling.

Overall, Class should not be fused with the tool it uses to execute an action, instead, it should be fused to the interface that will allow the tool to connect to the Class. Both Class and interface should not know how the tool works. However, the tool needs to meet the spicification of the interface.

This principle aims to reduce the dependency of high level Class on low level Class by introducing interfaces

SOLID implements in React Project

We are supposed to figure SOLID principle out through the above explaination. So then we are gonnar research how use them in React Project one after another.

S

For instance, let's implement a fitter component of products with fetching daata

typescript 复制代码
import { useState, useMemo, useEffect, ChangeEvent } from 'react';
import data from '../mock';

type Products = typeof data;

export default function Bad() {
    const [products, setProducts] = useState<Products>([]);
    const [filterFeatured, setFilterFeatured] = useState(true);

    const fetchProducts = async () => {
        const getMockData = (): Promise<Products> => new Promise(resolve => setTimeout(() => resolve(data), 0));
        const response = await getMockData();
        setProducts(response);
    };

    useEffect(() => {
        fetchProducts();
    }, []);

    const toggleFeatured = (e: ChangeEvent<HTMLSelectElement>) => {
        e.preventDefault();
        setFilterFeatured(e.target.value === '1');
    };

    const filteredProducts = useMemo(
        () => products.filter((product: Products[0]) => product.isFeatured === filterFeatured),
        [products, filterFeatured]
    );

    return (
        <>
            <div>
                <select
                    value={filterFeatured ? '1' : '0'}
                    onChange={toggleFeatured}
                >
                    <option value="0">unfeatured</option>
                    <option value="1">featured</option>
                </select>
            </div>
            <ul>
                {filteredProducts.map(({ id, title, description, date, isFeatured }) => (
                    <li key={id}>
                        <h3>{title}</h3>
                        <p>{description}</p>
                        <p>{date} - {isFeatured ? 'featured' : 'unfeatured'}</p>
                    </li>
                ))}
            </ul>
        </>
    );
}

Abouve bad codes, all funcitons written in a component that does not confirm the single responsibility priciple. Let's split the functions into single. codes like this:

typescript 复制代码
// entrance
import Product from './product';
import Filter, { filterProducts } from './filter';
import { useProducts } from './hooks/useProducts';
import { useFeaturedFitler } from './hooks/useFeaturedFitler';

export default function Good() {
    const { products } = useProducts();
    const { filterFeatured, toggleFeatured } = useFeaturedFitler();

    return (
        <>
            <Filter
                filterFeatured={filterFeatured}
                toggleFeatured={toggleFeatured}
            />
            <ul>
                {filterProducts(products, filterFeatured).map(product => (
                    <Product product={product} />
                ))}
            </ul>
       </>
    );
}
  • hooks

  • product
  • Fitter

O

For instance, we are gonnar build a Button component.

Abouve bad codes, we have to modify the codes of the Button component that it comes with new requirements, that's we are not expecting. Therefore, the component should be scale instead of modification. Let's code like this:

L

For instance, Let's we build a SearchInput component.

I

That's so bad. The Image component only needs imageUrl from props, but we transport the whole product data. It's not necessary. So we can do it like this:

D

For instance. Let's build a sign-in Form component.

It's not appropriate to change the form's codes once we have to change the logic of submit function, that's a problem. What the submit do should be abstract devised and picked out from here, by props to execute from external implementation from out of the component. So we shoud code like this:

Summary

So far, we have knew these five priciples and underline their details. They are to help us make code easy to adjust, extend and test without unexpected problems.

If you want to get codes of this articles. you can visit my github.

相关推荐
2401_860494706 分钟前
在React Native中开发进度条组件,可以使用多种方式来实现,包括使用内置的`ProgressViewharmony`(仅限harmony)
javascript·react native·react.js
海上彼尚13 分钟前
React18+快速入门 - 1.响应式机制之 useState 和 useReducer
前端·javascript·react.js
NOVAnet202318 分钟前
React曝“炸弹级”漏洞(CVE-2025-55182),CVSS 10.0分!已有在野利用,企业如何紧急防御
前端·react.js·网络安全·前端框架
2401_8604947020 分钟前
在React Native中实现一个Popover(气泡弹出框)组件,用于展示一些相关的信息,如提示、警告、错误等,同时支持自定义内容和位置
javascript·react native·react.js·ecmascript·harmonyos
海上彼尚25 分钟前
React18+快速入门 - 5.受控组件与非受控组件
前端·javascript·react.js
古韵27 分钟前
一个让你爽歪歪的请求工具是怎样的
vue.js·react.js·node.js
2401_8604947042 分钟前
如何在React Native中,开发一个类似于鸿蒙组件(Hong Kong component)的NoticeBar(通知栏)组件呢?
javascript·react native·react.js·ecmascript·kong·harmonyos
赵财猫._.43 分钟前
React Native鸿蒙开发实战(四):路由导航与多页面应用
react native·react.js·harmonyos
2401_8603195213 小时前
在React Native鸿蒙跨平台开发中实现一个冒泡排序算法并将其应用于数据排序,如何进行复制数组以避免直接修改状态中的数组
javascript·算法·react native·react.js·harmonyos