【React 开发】增强你的React 技能:2024年要掌握的4种高级模式

React由于其简单和灵活,近年来已成为最受欢迎的前端库之一。然而,当应用程序的复杂性扩展时,管理状态、处理异步输入和维护可扩展的体系结构可能会变得困难。我们将在本文中介绍四种高级React模式,它们将帮助您克服这些困难以及如何组合它们:

  • 前端模式的后端(BFF)
  • 挂钩模式
  • 高阶组件模式
  • 观察者模式
  • 将其整合在一起

前端模式的后端(BFF)

后端对前端(BFF)模式允许您开发具有单独后端的React应用程序,该后端管理所有API查询和数据处理。这有助于保持前端代码的简单性和清洁性,并可以提高应用程序性能。

当使用像Next.js这样的框架时,实现这一点就更容易了,因为它有一个集成的API路由系统,使您能够为前端应用程序快速构建API服务。这只是一种可能性,不需要在应用程序中使用它来实现BFF模式。

那么,在React应用程序中使用BFF模式什么时候可能有利呢?一个例子是有一个既大型又复杂的前端应用程序,它有几个API调用、数据处理和聚合职责,例如仪表板。通过将重处理逻辑与前端分离,您可以创建一个更具可扩展性和可维护性的体系结构。

如果您有许多共享可比数据和API查询的前端应用程序,那么使用BFF模式也可以帮助您避免重复代码,并促进应用程序中的代码重用。

带/不带BFF

import { useState } from 'react';

function MyComponent() {
  const [data, setData] = useState([]);

  const processData = (rawData) => {
    // super long and complex data processing here
  };

  const loadData = () => {
    const rawData = [
      { id: 1, title: 'Smartphone', category: 'electronics' },
      { id: 2, title: 'Laptop', category: 'electronics' },
      { id: 3, title: 'Chair', category: 'furniture' },
      { id: 4, title: 'Table', category: 'furniture' },
    ];

    const processedData = processData(rawData);
    setData(processedData);
  };

  loadData();

  return (
    <div>
      {data.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </div>
  );
}

W/ BFF

import { useEffect, useState } from 'react';
import axios from 'axios';

const API_URL = 'https://my-bff-service.com';

function MyComponent({ data }) {
  return (
    <div>
      {data.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </div>
  );
}

function MyBFFComponent() {
  const [data, setData] = useState([]);

  useEffect(() => {
    axios.get(`${API_URL}/my-data`).then((response) => {
      setData(response.data);
    });
  }, []);

  return <MyComponent data={data} />;
}

在本例中,我们向我们的BFF服务提出请求,该服务对我们的数据进行预处理,这样我们就不需要在前端进行预处理了,而且作为一个好处,我们减少了客户端的负载。然而,使用这种模式并不总是有益的,我们必须考虑API请求的延迟。只有当客户端处理和数据聚合显著降低我们的前端速度时,例如过多的网络请求、大型数据集上的复杂转换或其他类似情况时,将我们的数据处理卸载到API才是有利的。

挂钩模式

React中的hook模式是一个很好的特性,它允许我们在多个组件之间重用有状态行为。挂钩是使我们能够在功能组件中利用React的状态和其他功能的功能。

我们在前面的例子中使用的“useState”钩子是最常见的钩子之一。然而,还有许多其他挂钩可用,例如“useEffect”挂钩,它使我们能够在组件中执行副作用,以及“useContext”挂钩,使我们能够访问整个应用程序的全局数据。

下面是一个示例,说明如何使用功能组件来构造自定义挂钩,以处理从API获取数据:

import { useState, useEffect } from 'react';
import axios from 'axios';

function useFetch(url) {
  const [data, setData] = useState([]);
  useEffect(() => {
    axios.get(url).then((response) => {
      setData(response.data);
    });
  }, [url]);
  return data;
}
function MyComponent() {
  const data = useFetch('https://my-api.com/my-data');
  return (
    <div>
      {data.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </div>
  );
}

在本例中,我们创建了一个名为useFetch的自定义挂钩,它将URL作为参数,并从API返回数据。然后,我们在“MyComponent”组件中使用这个钩子来获取和显示我们的数据。通过创建自定义挂钩,我们可以跨多个组件重用有状态逻辑,并创建一个更模块化和可维护的体系结构。

注意:虽然React钩子可以被声明,看起来像正常的函数,但它们是唯一的,因为它们是唯一能够“挂钩”到React的状态和生命周期中的函数类型,它们很容易被发现,因为它们总是以“use”为前缀`

高阶组件模式

对于希望重用和组合代码的React开发人员来说,高阶组件(HOC)设计模式是一个强大的工具。HOC是接受组件作为输入并返回具有增强功能的新组件的功能。

HOC的一个流行应用程序用例是执行身份验证。例如,我们可能会编写一个功能组件,检查身份验证,然后呈现指定的组件或重定向到登录页面。然后,该组件可以封装在HOC中,以向我们想要保护的任何其他组件添加身份验证功能。

这种模式有助于抽象几个组件中可能需要的通用功能,使我们的代码更加模块化,更易于维护。此外,HOC可以跨多个组件重用,避免代码重复。

最终,HOC可能是提高React组件功能和可重用性的好工具,而且它们在集成身份验证等跨领域问题方面尤其有效。

import React from 'react';

function withAuth(WrappedComponent) {
  return function WithAuth(props) {
    const [isLoggedIn, setIsLoggedIn] = useState(false);
    useEffect(() => {
      // Check if the user is logged in
      const isLoggedIn = true; // Replace with actual authentication logic
      setIsLoggedIn(isLoggedIn);
    }, []);
    if (!isLoggedIn) {
      return <p>You must be logged in to access this content.</p>;
    }
    return <WrappedComponent {...props} />;
  };
}
function MyComponent() {
  return <p>This is protected content that requires authentication.</p>;
}
export default withAuth(MyComponent);

在这个例子中,我们编写了一个名为“withAuth”的HOC,它将一个组件作为输入,并生成一个包含身份验证逻辑的新组件。然后,这个HOC被用于我们的“MyComponent”组件,以保护我们的内容和请求身份验证。

观察者模式

观察器模式允许我们通过自动将一个对象中的更改传播给其所有订阅者来构建对象之间的一对多关系。这种方法在React应用程序中非常有用,用于控制状态和数据流。

我们可以利用内置的“useContext”钩子在React中创建观察者模式,这允许我们在不必显式提供道具的情况下向下传输数据。

以下是我们如何在应用程序中使用功能组件构建观察者的示例:

import { createContext, useContext, useState, useEffect } from 'react';

const MyContext = createContext([]);

function MyProvider(props) {
  const [data, setData] = useState([]);
  useEffect(() => {
    // Fetch data from the API
    const newData = [...]; // Replace with actual data
    setData(newData);
  }, []);
  return <MyContext.Provider value={data}>{props.children}</MyContext.Provider>;
}

function MyObserver() {
  const data = useContext(MyContext);
  return (
    <div>
      {data.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </div>
  );
}

function App() {
  return (
    <MyProvider>
      <MyObserver />
    </MyProvider>
  );
}

在本例中,我们构建了一个“MyProvider”提供程序组件,该组件从API接收数据,并使用“useContext”钩子将其发送给其子级。然后使用“MyObserver”组件显示来自提供程序的数据。通过使用观测器模式,我们可以在React应用程序中构建一个更灵活、更可维护的架构来控制状态和数据流。

将其整合在一起

大型应用程序通常将许多模式组合在一起,形成一个更复杂的体系结构。为了构建一个可扩展和健壮的前端架构,我们可以将BFF模式、hooks模式、HOC模式和observer模式等模式集成到一个解决方案中。

以下是我们如何在应用程序中使用功能组件来混合这些模式的示例:

import { createContext, useContext, useState, useEffect, useMemo } from 'react';
import axios from 'axios';

const API_URL = 'https://example.com/my-bff-service';
const MyContext = createContext([]);

function withAuth(WrappedComponent) {
  return function WithAuth(props) {
    const [isLoggedIn, setIsLoggedIn] = useState(false);

    useEffect(() => {
      // Check if the user is logged in
      const isLoggedIn = true; // Replace with actual authentication logic
      setIsLoggedIn(isLoggedIn);
    }, []);

    if (!isLoggedIn) {
      return <div>You must be logged in to access this content.</div>;
    }
    
    return <WrappedComponent {...props} />;
  };
}

function useFetch(url) {
  const [data, setData] = useState([]);
  
  useEffect(() => {
    axios.get(url).then((response) => {
      setData(response.data);
    });
  }, [url]);
  
  return data;
}

const AuthenticatedMyComponent = withAuth(function MyComponent() {
  
  return (
    <div>
      {data.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </div>
  );
});

function MyObserver() {
  const data = useContext(MyContext);
  
  return (
    <div>
      {data.map((item) => (
        <div key={item.id}>{item.title}</div>
      ))}
    </div>
  );
}

function MyProvider({ children }) {
  const data = useFetch(`${API_URL}/my-data`);
  const value = useMemo(() => data), [data])

  return (
    <MyContext.Provider value={value}>
      {children}
    </MyContext.Provider>
  );
}

function App() {
  return (
    <MyProvider>
      <AuthenticatedMyComponent />
      <MyObserver />
    </MyProvider>
  );
}

export default App;

在本例中,我们将上述所有模式组合到一个应用程序中。我们使用“MyProvider”组件向“MyComponent”和“MyObserver”组件提供数据。我们还使用“withAuth”HOC来保护MyComponent组件中的内容,并使用“useFetch”钩子从BFF服务中提取数据。所有这些模式结合在一起简化了我们代码库的所有复杂接口,现在我们可以轻松无重复地创建新功能。

总之,我们在本文中讨论的四种高级React模式可以帮助您构建更复杂、更健壮的应用程序。通过利用所有这些模式,您可以更好地管理状态,处理异步数据,并更好地分散处理负载。通过将它们应用于您自己的应用程序,您可以将React技能提升到一个新的水平,并创建高效、干净和可靠的应用程序。

文章链接

【React 开发】增强你的React 技能:2023年要掌握的4种高级模式 | 程序员云开发,云时代的程序员.

欢迎收藏【架构师酒馆】和【开发者开聊】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/217307.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(C语言)判定一个字符串是否是另一个字符串的子串,若是则返回子串在主串中的位置。

要求&#xff1a; &#xff08;1&#xff09;在主函数中输入两个字符串&#xff0c;调用子函数cmpsubstr()判断&#xff0c;并在主函数输出结果。 &#xff08;2&#xff09;子函数的返回值为-1表示未找到&#xff0c;否则返回子串的位置&#xff08;起始下标&#xff09;。 …

人工智能-A*算法-八数码问题

一&#xff0c;A*算法设计思想 A*算法&#xff08;A-star&#xff09;是一种寻路算法&#xff0c;主要用于游戏、机器人等领域。 它的设计思想是将最短路径搜索问题转化为一个优化问题&#xff0c;通过计算每个节点的评分&#xff08;f(n) g(n) h(n)&#xff09;来寻找最优…

YOLOv8-Seg改进:简单高效的模块-现代反向残差移动模块 (iRMB) | | ICCV2023 EMO

🚀🚀🚀本文改进:设计了一种面向移动端应用的简单而高效的现代反向残差移动模块 (Inverted Residual Mobile Block, iRMB),它吸收了类似 CNN 的效率来模拟短距离依赖和类似 Transformer 的动态建模能力来学习长距离交互,引入YOLOV8 🚀🚀🚀YOLOv8-seg创新专栏:h…

【华为OD题库-064】最小传输时延I-java

题目 某通信网络中有N个网络结点&#xff0c;用1到N进行标识。网络通过一个有向无环图.表示,其中图的边的值表示结点之间的消息传递时延。 现给定相连节点之间的时延列表times[]{u&#xff0c;v&#xff0c; w)&#xff0c;其中u表示源结点&#xff0c;v表示目的结点&#xff0…

小程序长按识别二维码

小程序开发中要实现长按识别二维码的功能很简单&#xff0c;只需要在image标签里添加如下属性即可&#xff1a; 小程序版本&#xff1a; show-menu-by-longpress"{{true}}" uniapp版本&#xff1a; :show-menu-by-longpress"true" 举例&#xff1a; …

金融银行业更适合申请哪种SSL证书?

在当今数字化时代&#xff0c;金融行业的重要性日益增加。越来越多的金融交易和敏感信息在线进行&#xff0c;金融银行机构必须采取必要的措施来保护客户数据的安全。SSL证书作为一种重要的安全技术工具&#xff0c;可以帮助金融银行机构加密数据传输&#xff0c;验证网站身份&…

网页文章采集工具-人工智能AI功能

简数采集器是一款支持人工智能AI功能的网页文章采集工具&#xff0c;它可以调用百度的文心一言AI对采集的数据进行分析&#xff0c;处理&#xff0c;内容创作等等&#xff0c;根据你的需求进行更加灵活的数据采集和处理。 文心一言人工智能AI功能使用方法&#xff1a; 1. 填写…

什么是Overlay网络?Overlay网络与Underlay网络有什么区别?

你们好&#xff0c;我的网工朋友。 在传统历史阶段&#xff0c;数据中心的网络是以三层架构&#xff08;核心、汇聚、接入&#xff09;为基本标准。 但是随着技术的发展&#xff0c;不同的厂家有不同的组建方式&#xff0c;比如说在核心层、汇聚层和接入层增加虚拟化技术。 …

MySQL笔记-第05章_排序与分页

视频链接&#xff1a;【MySQL数据库入门到大牛&#xff0c;mysql安装到优化&#xff0c;百科全书级&#xff0c;全网天花板】 文章目录 第05章_排序与分页1. 排序数据1.1 排序规则1.2 单列排序1.3 多列排序 2. 分页2.1 背景2.2 实现规则2.3 拓展 第05章_排序与分页 讲师&#…

Allegro无法模块复用的解决办法

Allegro无法模块复用的解决办法 在用Allegro做PCB设计的时候,模块复用是使用的比较频繁的功能,对于有相同模块的单板,可以节省大量的时间。 模块复用的功能不细说,具体参考以前的文章。 有时会遇到模块复用的时候出现如下报错 无法匹配,有时如果因为Device而无法复用,就…

学习pytorch16 现有网络模型的使用和修改

现有网络模型的使用和修改 官网 [https://pytorch.org/](https://pytorch.org/)torchvison 相关model1. 图像常用vgg16模型 【vgg19也常用】2. ImageNet数据集太大 无法代码下载 kaggle网址下载3. 代码4. 执行结果 官网 https://pytorch.org/ torchvison 相关model 1. 图像常用…

Android wifi 框架以及Enable流程

Android P相比于Android O的变化 多了WifiStateMachinePrime&#xff08;状态机的前处理机制&#xff09;&#xff0c;wifiService的相关cmd 不再是直接send 给WifiStateMachine&#xff0c;而是被送到WifiStateMachinePrime先进行处理后&#xff0c;再送往WifiStateMachine也…

Linux Namespace技术

对应到容器技术&#xff0c;为了隔离不同类型的资源&#xff0c;Linux 内核里面实现了以下几种不同类型的 namespace。 UTS&#xff0c;对应的宏为 CLONE_NEWUTS&#xff0c;表示不同的 namespace 可以配置不同的 hostname。User&#xff0c;对应的宏为 CLONE_NEWUSER&#xf…

Redis Hash数据类型

Redis Hash数据类型 几乎所有的主流编程语言都提供了哈希(hash)类型&#xff0c;它们的叫法可能是哈希、字典、关联数组、映射。在 Redis 中&#xff0c;哈希类型是指值本身又是一个键值对结构&#xff0c;形如key “key”&#xff0c;value {ffield1, value1 }, … {fieldN…

HTTP 缓存机制

一、强制缓存 只要浏览器判断缓存没有过期&#xff0c;则直接使用浏览器的本地缓存而无需再请求服务器。 强制缓存是利用下面这两个 HTTP 响应头部&#xff08;Response Header&#xff09;字段实现的&#xff0c;它们都用来表示资源在客户端缓存的有效期&#xff1a; Cache…

对抗神经网络 CGAN实战详解 完整数据代码可直接运行

代码视频讲解: 中文核心项目:对抗神经网络 CGAN实战详解 完整代码数据可直接运行_哔哩哔哩_bilibili 运行图: 完整代码: from keras.layers import Input, Dense, Reshape, Flatten, Dropout, multiply from keras.layers import BatchNormalization, Activation, Embedd…

单片机系统

我们来看单片机 的例子&#xff0c;读者可能会担心单片机&#xff08;又称MCU&#xff0c;或微控制器&#xff09; 过于专业而无法理解。完全没必要&#xff01;在这里我们仅借它谈论一下有关时间的话题&#xff0c;顺带提一下单片机系统的概念。 单片机顾名思义是集成到一个芯…

Java开发中一些重要软件安装配置

Java技术栈中重要过程 1、JavaWeb1、开发工具VsCode的安装和使用2、Tomcat服务器3、nodejs的简介和安装4、Vite创建Vue3工程化项目ViteVue3项目的创建、启动、停止ViteVue3项目的目录结构 5、Maven安装和配置 1、JavaWeb 1、开发工具VsCode的安装和使用 1 安装过程 安装过程比…

IDEA插件:Apipost-Helper

Apipost-Helper是由Apipost推出的IDEA插件&#xff0c;写完接口可以进行快速调试&#xff0c;且支持搜索接口、根据method跳转接口&#xff0c;还支持生成标准的API文档&#xff0c;注意&#xff1a;这些操作都可以在代码编辑器内独立完成&#xff0c;非常好用&#xff01;这里…

RocketMQ Copilot 一款面向 Apache RocketMQ 的智能辅助运维系统

一、RocketMQ简介 ocketMQ是阿里巴巴研发的一款分布式消息中间件&#xff0c;后开源给Apache基金会&#xff0c;成为apache的顶级开源项目。它具有高性能、高可靠、高实时和分布式的特点。RocketMQ主要应用于解决应用耦合&#xff0c;消息分发&#xff0c;流量削锋等问题。 R…