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

news2024/12/23 23:23:09

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.coloradmin.cn/o/1284215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity中C#使用协程控制Shader材质变化

文章目录 前言一、协程是什么二、在Unity中使用协程1、我们在 Start 中测试一下协程的执行顺序2、我们实现一个点击按钮实现角色受击效果 三、协程中的动画过渡1、首先&#xff0c;在协程内实现中毒并且消散的效果2、在 OnGUI 内&#xff0c;给一个新按钮使用刚刚定义的协程 四…

算法基础六

搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2 示例 2: 输入: nums [1,3,5,6], target 2 输…

TCP 半连接队列和全连接队列

在 TCP 三次握手的时候&#xff0c;Linux 内核会维护两个队列&#xff0c;分别是&#xff1a; 半连接队列&#xff0c;也称 SYN 队列&#xff1b; 全连接队列&#xff0c;也称 accept 队列&#xff1b; 服务端收到客户端发起的 SYN 请求后&#xff0c;内核会把该连接存储到半连…

创新零售巨头:揭开山姆与Costco蓬勃发展背后的秘密

会员制商店这个冷门的业态突然之间硝烟弥漫&#xff0c;更多的资本开始涌向付费会员商店这一业态&#xff0c;本文即将探讨的是付费会员制的成功秘诀和零售企业可行的发展路径。Costco的发展经验对国内超市巨头的崛起具有显著的借鉴意义&#xff0c;以优质低价商品服务为中心&a…

辛普森距离(SD,Sampson Distance)

定义 Sampson误差是复杂性介于代数误差和几何误差之间&#xff0c;但非常近似于几何误差的一种误差。 应用 SLAM对极几何中使用到SD来筛选内点&#xff1a; 1.随机采样8对匹配点 2.8点法求解基础矩阵 ​&#xff1b; 3.奇异值约束获取基础矩阵F&#xff1b; 4.计算误差&…

前端开发_CSS

CSS定义 层叠样式表 (Cascading Style Sheets&#xff0c;缩写为 CSS&#xff09;&#xff0c;是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现&#xff08;美化内容&#xff09; 书写位置&#xff1a;title 标签下方添加 style 双标签&#xff0c;style 标签里面书…

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

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

Windows本地搭建WebDAV服务并使用内网穿透远程访问【无公网IP】

windows搭建WebDAV服务&#xff0c;并内网穿透公网访问【无公网IP】 文章目录 windows搭建WebDAV服务&#xff0c;并内网穿透公网访问【无公网IP】1. 安装IIS必要WebDav组件2. 客户端测试3. cpolar内网穿透3.1 打开Web-UI管理界面3.2 创建隧道3.3 查看在线隧道列表3.4 浏览器访…

Unity Meta Quest 一体机开发(八):【手势追踪】实现 Hand Grab 扔物体功能

文章目录 &#x1f4d5;教程说明&#x1f4d5;设置刚体和碰撞体&#x1f4d5;给物体添加 Physics Grabbable 脚本&#x1f4d5;给手部添加 Hand Velocity Calculator 物体 此教程相关的详细教案&#xff0c;文档&#xff0c;思维导图和工程文件会放入 Spatial XR 社区。这是一…

SAS聚类分析介绍

1 聚类分析介绍 1.1基本概念 聚类就是一种寻找数据之间一种内在结构的技术。聚类把全体数据实例组织成一些相似组&#xff0c;而这些相似组被称作聚类。处于相同聚类中的数据实例彼此相同&#xff0c;处于不同聚类中的实例彼此不同。聚类技术通常又被称为无监督学习&#xff0…

2023博思高科技智慧车行、人行专项研讨会成功召开

来源&#xff1a;智安物联网 11月30日&#xff0c;深圳市博思高科技有限公司&#xff08;以下简称“博思高科技”&#xff09;在其总部成功举办了智慧车行、人行专项研讨会议。本次会议邀请了来自国家发改委综合运输研究所的程世东主任&#xff0c;中国安全防范产品行业协会原…

13、pytest为失败的断言定义自己的解释

官方实例 # content of ocnftest.py from test_foocompare import Foodef pytest_assertrepr_compare(op, left, right):if isinstance(left, Foo) and isinstance(right, Foo) and op "":return["Comparing Foo instances:",f" vals:{left.val} !…

第一个小记录达成:第一个年费会员用户

早上看到&#xff0c;欸&#xff0c;有个用户好像充了 9.9 元&#xff0c;挺开心&#xff0c;刚刚看飞书消息&#xff0c;看到了这条分享给朋友&#xff0c;等等&#xff0c;是充值了 99 元&#xff0c;有个用户充了年费&#xff0c;偶买噶&#xff0c;开心 &#x1fae1; 这是…

Mysql集群部署---MySQL集群Cluster将数据分成多个片段,每个片段存储在不同的服务器上

1.1 目的 部署MysqlCluster集群环境 1.2 MySQL集群Cluster原理 1 数据分片 MySQL集群Cluster将数据分成多个片段&#xff0c;每个片段存储在不同的服务器上。这样可以将数据负载分散到多个服务器上&#xff0c;提高系统的性能和可扩展性。 2. 数据同步 MySQL集群Cluster使…

技术省钱攻略:代理IP是的最佳计费方式是什么?

代理IP是很多互联网企业最常使用的工具之一&#xff0c;它在我们进行很多互联网业务时都可以帮助企业提高效率和保护隐私。在使用代理IP的过程中&#xff0c;一般用户需要根据自己的需求和预算选择合适的计费方式&#xff0c;今天就让我们一起探讨一下代理IP的最佳计费方式是什…

(C语言)求出1,2,5三个数不同个数组合为100的组合个数

#include<stdio.h> int main() {int count;for(int i 0;i < 100;i )for(int j 0;j < 50;j )for(int k 0;k < 20;k ){if(i j*2 k*5 100){count;printf("100可以拆分为%d个1元&#xff0c;%d个2元&#xff0c;%d个5元\n",i,j,k);} }printf("…

FPGA时序分析与时序约束(一)

一、为什么要进行时序分析和时序约束 PCB通过导线将具有相关电气特性的信号相连接&#xff0c;这些电气信号在PCB上进行走线传输时会产生一定的传播延时。 而FPGA内部也有着非常丰富的可配置的布线资源&#xff0c;能够让位于不同位置的逻辑资源块、时钟处理单元、BLOCK RAM、D…

【初阶解法-数据结构】包含min函数的栈(代码+图示)

【数据结构】刷题-包含min函数的栈(代码图示)-初阶解法 文章目录 【数据结构】刷题-包含min函数的栈(代码图示)-初阶解法题目提炼题目要求分析题目总结思路代码时间/空间复杂度进阶版 题目 定义栈的数据结构&#xff0c;请在该类型中实现一个能够得到栈中所含最小元素的 min 函…

SpringBoot——嵌入式 Servlet容器

一、如何定制和修改Servlet容器的相关配置 前言&#xff1a; SpringBoot在Web环境下&#xff0c;默认使用的是Tomact作为嵌入式的Servlet容器&#xff1b; 【1】修改和server相关的配置&#xff08;ServerProperties实现了EmbeddedServletContainerCustomizer&#xff09;例如…

华为交换机,配置攻击防范示例

攻击防范简介 定义 攻击防范是一种重要的网络安全特性。它通过分析上送CPU处理的报文的内容和行为&#xff0c;判断报文是否具有攻击特性&#xff0c;并配置对具有攻击特性的报文执行一定的防范措施。 攻击防范主要分为畸形报文攻击防范、分片报文攻击防范和泛洪攻击防范。 …