【React设计】React企业级设计模式

Image Source : https://bugfender.com
React是一个强大的JavaScript库,用于构建用户界面。其基于组件的体系结构和构建可重用组件的能力使其成为许多企业级应用程序的首选。然而,随着应用程序的规模和复杂性的增长,维护和扩展变得更加困难。这就是设计模式发挥作用的地方。在这篇博客文章中,我们将探讨一些最常用的React企业设计模式,以及TypeScript中的代码示例。
容器和呈现组件模式
React中使用最广泛的模式之一是容器和表示组件模式。这种模式将表示逻辑与业务逻辑分离,使代码更加模块化,更易于测试。容器组件负责从服务器获取数据,并将其作为prop 传递给表示组件。表示组件负责呈现UI。
// Container Component
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUsers } from './userActions';
import { RootState } from './rootReducer';
import UserList from './UserList';const UserListContainer: React.FC = () => {const dispatch = useDispatch();const { loading, users } = useSelector((state: RootState) => state.users);useEffect(() => {dispatch(fetchUsers());}, [dispatch]);return <UserList loading={loading} users={users} />;
};export default UserListContainer;// Presentational Component
import React from 'react';
import { User } from './userTypes';interface Props {loading: boolean;users: User[];
}const UserList: React.FC<Props> = ({ loading, users }) => {if (loading) return <div>Loading...</div>;if (!users) return null;return (<ul>{users.map((user) => (<li key={user.id}>{user.name}</li>))}</ul>);
};export default UserList;
渲染Props 图案
“渲染prop ”模式是一种使用值为函数的prop 在组件之间共享代码的技术。当组件具有相似的功能但具有不同的渲染要求时,此模式非常有用。
import React from 'react';interface Props {render: (count: number, increment: () => void) => JSX.Element;
}const Counter: React.FC<Props> = ({ render }) => {const [count, setCount] = React.useState(0);const increment = () => {setCount(count + 1);};return render(count, increment);
};export default Counter;// Usage
import React from 'react';
import Counter from './Counter';const App: React.FC = () => {return (<div><h1>Render Props Pattern</h1><Counterrender={(count, increment) => (<div><p>Count: {count}</p><button onClick={increment}>Increment</button></div>)}/></div>);
};export default App;
高阶组件模式。
高阶组件(HOC)模式是React中的一种设计模式,它通过提供一种增强或修改组件功能的方法来实现组件的可重用性和代码共享。
简单地说,HOC是一个函数,它接受一个组件作为参数,并返回一个具有附加功能的新组件。然后,可以像React中的任何其他组件一样渲染新组件。原始组件由HOC包裹,HOC为包裹的组件提供额外的行为或prop 。
HOC可用于广泛的任务,如提供上下文、处理错误、获取数据或强制身份验证。它们可以帮助减少代码重复,提高代码可维护性,并促进代码重用。
import React from 'react';// Define a higher-order component
const withName = (WrappedComponent) => {return class extends React.Component {state = {name: 'John Doe'}render() {return (<WrappedComponent name={this.state.name} {...this.props} />)}}
}// Define a regular component
const MyComponent = (props) => {return (<div><p>Hello, my name is {props.name}.</p><p>I am a {props.role}.</p></div>)
}// Wrap MyComponent with the withName HOC
const MyComponentWithName = withName(MyComponent);// Render MyComponentWithName
const App = () => {return (<div><MyComponentWithName role="developer" /></div>)
}export default App;
禁用prop 模式
禁用prop模式是React中使用的一种设计模式,它通过提供一种方法来禁用按钮、链接和表单字段等交互元素(当它们不可用或不适用时),从而能够创建可访问的用户界面。
该模式包括向组件中的交互式元素添加一个禁用的prop ,当设置为true时,将禁用该元素并阻止其接收用户输入。这对于由于特定条件(例如表单不完整或用户权限不足)导致交互式元素不适用的情况尤其有用。
import React from 'react';const App = () => {return (<div><SomeComponent disabled /></div>);
};const SomeComponent = ({ disabled = false }) => {return (!disabled && (<div><h2>Disable SomeComponent to see magic happen!</h2></div>));
};
受控和非受控组件模式
受控组件是一个表单元素,其值由React控制。换句话说,组件的值总是通过props显式设置,并通过回调进行更新。这意味着组件的状态始终与输入数据同步,允许React控制组件的行为,并允许开发人员轻松处理用户输入。
import React, { useState } from 'react';function ControlledInput() {const [value, setValue] = useState('');const handleChange = (event) => {setValue(event.target.value);};return (<input type="text" value={value} onChange={handleChange} />);
}
不受控制的零部件是由浏览器管理其值的形状元素。换句话说,组件的值由用户设置,React不控制其行为。这会使处理复杂表单中的用户输入变得更加困难,但在简单表单中使用也会更快、更容易。
import React, { useRef } from 'react';function UncontrolledInput() {const inputRef = useRef(null);const handleSubmit = (event) => {event.preventDefault();console.log(inputRef.current.value);};return (<form onSubmit={handleSubmit}><input type="text" ref={inputRef} /><button type="submit">Submit</button></form>);
}
复合部件模式
复合组件模式是React中用于管理由多个子组件组成的组件的设计模式。这种模式包括将父组件的关注点分离为较小的组件,然后使用prop 、上下文和其他技术的组合来管理这些较小组件之间的关系。
复合组件模式背后的理念是为开发人员提供一种方法,以创建由较小构建块组成的可重复使用、灵活和易于使用的组件。这使开发人员能够创建复杂的UI组件,这些组件可以很容易地进行自定义和扩展,同时仍然保持清晰易懂的代码结构。
import React, { createContext, useState } from 'react';const ToggleContext = createContext();function Toggle({ children }) {const [on, setOn] = useState(false);const toggle = () => setOn(!on);return (<ToggleContext.Provider value={{ on, toggle }}>{children}</ToggleContext.Provider>);
}function ToggleOn({ children }) {const { on } = useContext(ToggleContext);return on ? children : null;
}function ToggleOff({ children }) {const { on } = useContext(ToggleContext);return on ? null : children;
}function ToggleButton(props) {const { on, toggle } = useContext(ToggleContext);return <button onClick={toggle} {...props} />;
}function App() {return (<Toggle><ToggleOn>The button is on</ToggleOn><ToggleOff>The button is off</ToggleOff><ToggleButton>Toggle</ToggleButton></Toggle>);
}
prop 集合模式
prop 集合模式是React中用于将prop 集合传递给组件的设计模式。它包括将多个相关prop 组合成一个对象,然后将其作为一个prop 传递给组件。
当我们想将大量相关的prop 传递给组件时,这种模式特别有用,因为它可以减少代码中的混乱,并使prop 的管理变得更容易。
import React from 'react';function Button(props) {const { label, color, size, ...rest } = props;return (<button style={{ color, fontSize: size }} {...rest}>{label}</button>);
}function App() {const buttonProps = {label: "Click Me",color: "red",size: "20px",onClick: () => console.log("Button clicked!")};return <Button {...buttonProps} />;
}
函数作为子模式
Function as Child模式是React中使用的一种设计模式,它涉及将函数作为子级传递给组件,然后在组件内部调用该组件来呈现实际内容。
import React from 'react';function Toggle(props) {const [on, setOn] = useState(false);const handleToggle = () => {setOn(!on);};return props.children({on: on,toggle: handleToggle});
}function App() {return (<Toggle>{({ on, toggle }) => (<div>{on ? "The button is on" : "The button is off"}<button onClick={toggle}>Toggle</button></div>)}</Toggle>);
}
受控输入模式
受控输入模式是React中用于管理输入字段的模式。它包括将输入字段的当前值存储在组件状态中,并在输入值更改时使用事件处理程序更新状态。
import React, { useState } from "react";function ControlledInput() {const [inputValue, setInputValue] = useState("");const handleInputChange = (event) => {setInputValue(event.target.value);};return (<div><input type="text" value={inputValue} onChange={handleInputChange} /><p>The input value is: {inputValue}</p></div>);
}
不可变模式
不可变模式通常用于管理组件的状态。我们不直接修改状态,而是使用更新的值创建一个新的状态对象,然后将其传递给组件进行渲染。
Immutable.js库可用于创建不可变的数据结构,这些数据结构可用于React状态管理。以下是如何在React组件中使用不可变模式的示例:
import React, { Component } from 'react';
import { Map } from 'immutable';class MyComponent extends Component {state = {data: Map({name: 'John',age: 30,email: 'john@example.com'})};handleNameChange = (event) => {const name = event.target.value;const newData = this.state.data.set('name', name);this.setState({ data: newData });};render() {const { data } = this.state;return (<div><label>Name:</label><input type="text" value={data.get('name')} onChange={this.handleNameChange} /><label>Age:</label><span>{data.get('age')}</span><label>Email:</label><span>{data.get('email')}</span></div>);}
}
在这篇博客文章中,我们讨论了一些最常用的React企业设计模式,包括高阶组件、渲染prop 、容器表示组件模式、复合组件、受控组件等等。通过在React项目中应用这些设计模式和最佳实践,您可以提高代码质量,增加团队协作,并使您的应用程序更具可扩展性、灵活性和可维护性。然而,重要的是要记住,这些模式不是一刀切的解决方案,可能需要根据项目的具体要求进行调整。
总的来说,React企业设计模式是一套有价值的工具和技术,可以帮助您构建更好的React应用程序,提高开发生产力和效率,并提供满足用户和利益相关者需求的高质量软件。
编码快乐!
文章链接
【React设计】React企业设计模式 | 程序员云开发,云时代的程序员.
欢迎收藏【架构师酒馆】和【开发者开聊】
相关文章:
【React设计】React企业级设计模式
Image Source : https://bugfender.com React是一个强大的JavaScript库,用于构建用户界面。其基于组件的体系结构和构建可重用组件的能力使其成为许多企业级应用程序的首选。然而,随着应用程序的规模和复杂性的增长,维护和扩展变得更加困难。…...
赴日程序员高年薪过上“躺平”生活?
日本的IT行业想要达到的高薪,也是需要很多资历和经验的,不过即使你是新卒,也能拿到相比国内来说让你满意的薪资。 刚入职的起薪是20-23万日元/月,情报信息业出身,技术掌握不错,起薪是25万-30万日元。之后经…...
Windows开启SQL Server服及1433端口
需求:Windows开启SQL Server服务及1433端口 目前端口没有启动 解决: 打开SQL Server配置管理器(winR) 各个sqlserver版本在textbox中输入对应的命令如下: SQLServerManager15.msc(对于 SQL Server 2019 &am…...
网盘系统设计:万亿 GB 网盘如何实现秒传与限速?
Java全能学习面试指南:https://javaxiaobear.cn 网盘,又称云盘,是提供文件托管和文件上传、下载服务的网站(File hostingservice)。人们通过网盘保管自己拍摄的照片、视频,通过网盘和他人共享文件ÿ…...
整数和浮点数在内存中的存储
文章目录 每日一言整数在内存中的存储方式浮点数在内存中的存储结语 每日一言 You just can’t beat the person who never gives up. 你无法打败那位永不放弃的人。 整数在内存中的存储方式 整数在内存中的存储方式通常采用二进制形式,即将整数的数值转化为二进制…...
rabbitMQ镜像队列的使用
在rabbitMQ集群中,默认发送消息时,队列默认时在一个节点上存在的。 我们以node01 node02 node03三节点集群为例,在node01声明队列发送消息后,发现: 测试队列只在节点node01上出现。 我们手动停止node01后,…...
ros来保存图像和保存记录视频的方法---gmsl相机保存视频和图片
1,保存图片 rosrun image_view image_view image:=/myimg_topic这个命令只是用来查看图像的,它并不会保存图像。如果你想要保存图像,你需要使用image_saver节点,并指定保存路径。例如: 下面指令就可以了,可以用 rosrun image_view image_saver image:=/myimg_topic _fi…...
Oracle19c使用adrci清理日志文件
Oracle中通常有好多日志文件,遇到异常情况会产生大量日志,造成磁盘空间紧张。 故需要清理对应文件。包括trace文件,incident文件,listener log文件等。 19c中oracle提供了一个ADRCI的命令行工具来查看ADR中的alert日志和trace信息…...
Ubuntu之Sim2Real环境配置(坑居多)
不要一上来就复制哦,因为很多下面的步骤让我走了很多弯路,如果可能的话,我会重新整理再发出来 前提: 参考教程 Docs 创建工作空间(不用跟着操作,无用) 1.创建sim2real server container 1.尝试创建sim2r…...
java中BigDecimal里面的subtract函数的意思?
在Java中,BigDecimal类提供了一个名为subtract()的函数,用于执行两个BigDecimal对象的减法操作。该函数返回一个新的BigDecimal对象,表示两个操作数相减的结果。 下面是BigDecimal.subtract()函数的用法示例: java Copy code im…...
线程变量引发的session混乱问题
最近不是在救火,就是在救火的路上。 也没什么特别可写的,今天记录下最近遇到的一个问题,个人觉得挺有意思, 待有缘人阅读 言归正传,售后反馈: 营业查询中付款方式为第三方支付的几条银行缴费,创…...
dockerfile与docker-compose解释及对比
Dockerfile 是一个文本文件,用于定义单个Docker镜像的构建过程和配置。它包含了一系列的指令,如FROM、RUN、COPY、CMD等,按照顺序执行这些指令来构建镜像。Dockerfile可以定义容器的基础镜像、安装依赖软件、拷贝文件、运行命令等操作。通过…...
数据库更换版本
目录 0.前言 1.官网下载MySQL 2.配置初始化文件my.ini 3.初始化MySQL 4.安装mysql服务并启动修改密码 5.配置环境变量编辑 0.前言 心累,为了完成实验,必须使用8.0版本导致我更新版本的时候,把sqlyog干崩溃了,什么版本不兼…...
Unity Meta Quest 一体机开发(九):【手势追踪】通过录制抓取手势实现自定义抓取姿势
文章目录 📕教程说明📕录制前的准备📕第一种录制方法(Hand Grab Pose Tool 场景)⭐在运行模式中确认录制⭐保存录制的手势,将物体做成 Prefab⭐在编辑阶段调整抓取手势🔍Fingers Freedom&#x…...
Git 简介及异常场景处理
一、简介 介绍Git之前,还得先介绍下 版本控制系统(VCS), 和它的发展历史 纵观版本控制系统的发展历史,广义上讲,版本控制工具的历史可以分为三代: 第一代 第一代版本控制系统被称为本地版本控…...
龙迅LT2611UX 四端口LVDS转HDMI(2.0)
1.描述: LT2611UX 四端口LVDS TO HDMI2.0。 LT2611UX是一款高性能得LVDS到HDMI2.0转换器得STB,DVD应用程序,LVDS输入可以配置单端口,双端口或者四端口,带有一个高速时钟通道,最多可运行三到四个高速数据…...
MySQL基础『数据类型』
✨个人主页: 北 海 🎉所属专栏: MySQL 学习 🎃操作环境: CentOS 7.6 阿里云远程服务器 🎁软件版本: MySQL 5.7.44 文章目录 1.数据类型一览2.整型2.1.INT2.2.BIT 3.浮点数3.1.FLOAT3.2.DECIMAL3…...
SQL手工注入漏洞测试(PostgreSQL数据库)-墨者
———靶场专栏——— 声明:文章由作者weoptions学习或练习过程中的步骤及思路,非正式答案,仅供学习和参考。 靶场背景: 来源: 墨者学院 简介: 安全工程师"墨者"最近在练习SQL手工注入漏洞&#…...
STM32单片机项目实例:基于TouchGFX的智能手表设计(1)项目介绍及GUI界面基础
STM32单片机项目实例:基于TouchGFX的智能手表设计(1)项目介绍及GUI界面基础 一、项目介绍 1.1方案提供 1.2主控选择 1.3硬件平台 1.4 开发环境 1.5 关于华清 二、GUI界面基础 2.1.1 嵌入式绘图系统 2.1.1 色彩格式 2.1.1帧缓冲区 …...
【超详细教程】基于html+js实现轮播图
轮播图是现代网页设计中常见的元素之一,它能够展示多张图片或内容,在有限的空间内循环播放,提升网页的视觉效果和用户体验。下面将以一个简单的网页轮播图为例,说明如何基于HTML和JavaScript实现。 1、R5Ai智能助手 chatgpt国…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
