当前位置:首页 > 科技  > 软件

React中的依赖注入,看这一篇就够了!

来源: 责编: 时间:2023-09-28 10:03:16 341观看
导读React 组件不应该包含业务逻辑,你同意吗? 如果是,请继续阅读。 如果没有,请立即停止。 这篇文章是写给别人的。只需 3 个步骤即可将依赖注入添加到您的 React 项目中:创建一个“容器”来放置您的依赖项创建一个钩子 useInj

KC628资讯网——每日最新资讯28at.com

React 组件不应该包含业务逻辑,你同意吗? 如果是,请继续阅读。 如果没有,请立即停止。 这篇文章是写给别人的。KC628资讯网——每日最新资讯28at.com

只需 3 个步骤即可将依赖注入添加到您的 React 项目中:KC628资讯网——每日最新资讯28at.com

创建一个“容器”来放置您的依赖项KC628资讯网——每日最新资讯28at.com

创建一个钩子 useInject 来检索依赖项KC628资讯网——每日最新资讯28at.com

使用组件中的钩子KC628资讯网——每日最新资讯28at.com

长版

如果您对答案持观望态度,我将尝试为您提供一些关于为什么我们不应该这样做的见解:KC628资讯网——每日最新资讯28at.com

React 是一个用于创建用户界面的库; 这个定义应该阻止我们将业务逻辑放入组件中。KC628资讯网——每日最新资讯28at.com

包含业务逻辑的组件很难阅读、维护和测试。KC628资讯网——每日最新资讯28at.com

从组件中提取业务逻辑是一个能够重用它的好主意。KC628资讯网——每日最新资讯28at.com

好的,如果我们从组件中取出业务逻辑,我们应该将其编写在某个地方,例如外部类或函数中。 我们该怎么做呢? 通过使用依赖注入!KC628资讯网——每日最新资讯28at.com

什么是依赖注入,为什么要使用它

依赖注入 (DI) 是一种软件设计模式,它将对象的创建与其使用分开。 实际上,对象的实例化不是在使用它们的代码中创建事物,而是委托给负责创建对象并将其提供给需要它们的组件的外部实体。KC628资讯网——每日最新资讯28at.com

依赖注入旨在使代码更加灵活、模块化且易于测试。 DI 不是严格的、紧密耦合的代码,而是允许模块化组件轻松替换或扩展,而无需更改使用它们的代码。KC628资讯网——每日最新资讯28at.com

此外,DI 有助于提高代码的可读性和可维护性,因为它使组件之间的依赖关系变得明确,并有利于复杂依赖关系的管理。KC628资讯网——每日最新资讯28at.com

总之,依赖注入的作用是:KC628资讯网——每日最新资讯28at.com

将对象的创建与其使用分开KC628资讯网——每日最新资讯28at.com

使代码更加灵活、模块化且易于测试KC628资讯网——每日最新资讯28at.com

提高代码的可读性和可维护性。KC628资讯网——每日最新资讯28at.com

React 中的依赖注入

假设我们需要开发一个管理待办事项列表的 React 应用程序(多么奇特)。KC628资讯网——每日最新资讯28at.com

我们将有一个显示待办事项列表的组件。我们希望在渲染组件时从某些 API 加载列表。 由于我们不想在组件中编写业务逻辑,因此我们将拥有一个执行 API 调用的服务,我们可以在组件中使用该服务。 如该图所示。KC628资讯网——每日最新资讯28at.com

KC628资讯网——每日最新资讯28at.com

在此序列图中,组件通过调用方法或函数向服务发送数据请求。 然后,服务通过发送请求从外部 API 检索数据。 一旦接收到数据,服务就会对其进行处理并将其返回给组件。KC628资讯网——每日最新资讯28at.com

事件的顺序由图中的箭头指示。 从API到Service的虚线箭头表示从API检索数据,而从Service到Component的实线箭头表示将处理后的数据返回到Component。KC628资讯网——每日最新资讯28at.com

在实现级别,代码可能如下所示:KC628资讯网——每日最新资讯28at.com

import React, { useState, useEffect } from 'react';import TodoService from './TodoService';function TodoList() {  const [todos, setTodos] = useState([]);  useEffect(() => {    async function fetchTodos() {      try {        const todos = await TodoService.getTodos(); // Call TodoService to get todos        setTodos(todos);      } catch (error) {        console.error(error);      }    }    fetchTodos();  }, []);  return (    <ul>      {todos.map(todo => (        <li key={todo.id}>{todo.title}</li>      ))}    </ul>  );}export default TodoList;

在此代码中,我们定义了一个 TodoList 组件,该组件从 TodoService 调用 getTodos 方法。 我们使用 useState 挂钩来跟踪从服务返回的待办事项,并使用 useEffect 挂钩在组件安装时获取待办事项。KC628资讯网——每日最新资讯28at.com

当 fetchTodos 函数被调用时,它使用await关键字等待getTodos方法返回todos。 一旦待办事项返回并使用 setTodos 函数将其设置为待办事项状态变量。KC628资讯网——每日最新资讯28at.com

最后,我们使用地图函数渲染待办事项列表并显示每个待办事项的标题。 请注意,这是一个简化的示例,TodoService 的实现可能会根据所使用的 API 的不同而有所不同。KC628资讯网——每日最新资讯28at.com

使用 props 进行依赖注入

import React, { useState, useEffect } from 'react';function TodoList({ todoService }) {  const [todos, setTodos] = useState([]);  useEffect(() => {    async function fetchTodos() {      try {        const todos = await todoService.getTodos(); // Call injected TodoService to get todos        setTodos(todos);      } catch (error) {        console.error(error);      }    }    fetchTodos();  }, [todoService]);  return (    <ul>      {todos.map(todo => (        <li key={todo.id}>{todo.title}</li>      ))}    </ul>  );}export default TodoList;

在此更新的代码中,我们将 TodoService 作为 prop 注入到 TodoList 组件中。 该组件不再直接导入 TodoService,而是使用注入的服务来获取 todo。KC628资讯网——每日最新资讯28at.com

当组件安装时, fetchTodos 函数使用注入的 todoService 来检索 todos。 这样,我们可以通过将不同的服务实现传递给 TodoList 组件来轻松交换 TodoService 的实现。KC628资讯网——每日最新资讯28at.com

要将 TodoList 组件与 TodoService 的特定实现一起使用,我们将该服务作为 prop 传递,如下所示:KC628资讯网——每日最新资讯28at.com

import React from 'react';import TodoService from './TodoService';import TodoList from './TodoList';function App() {  return <TodoList todoService={TodoService} />;}export default App;

通过将 TodoService 作为 prop 传递给 TodoList 组件,我们实现了更加模块化和灵活的设计,因为我们可以轻松地在 TodoService 的不同实现之间切换,而无需更改 TodoList 组件。KC628资讯网——每日最新资讯28at.com

在为组件编写测试时,这非常有用。KC628资讯网——每日最新资讯28at.com

此时,我们有两个问题:KC628资讯网——每日最新资讯28at.com

我们仍然需要将 TodoService 导入到 App 组件中,该组件不使用依赖注入。KC628资讯网——每日最新资讯28at.com

props 只是在应用程序中传输数据的有效方法之一,因为它们仅适用于嵌套层。KC628资讯网——每日最新资讯28at.com

KC628资讯网——每日最新资讯28at.com

该图显示了 props 如何通过组件的层次结构传递。 组件缩进得越多,它在组件树中的嵌套就越深。 我们不想要这种嵌套。KC628资讯网——每日最新资讯28at.com

使用 React Context 进行依赖注入

下面是使用 TodoContext 从组件调用 TodoService 的 React 代码示例:KC628资讯网——每日最新资讯28at.com

import React, { useState, useEffect, useContext } from 'react';import TodoContext from './TodoContext';function TodoList() {  const [todos, setTodos] = useState([]);  const todoService = useContext(TodoContext); // Retrieve TodoService from TodoContext  useEffect(() => {    async function fetchTodos() {      try {        const todos = await todoService.getTodos(); // Call TodoService from TodoContext to get todos        setTodos(todos);      } catch (error) {        console.error(error);      }    }    fetchTodos();  }, [todoService]);  return (    <ul>      {todos.map(todo => (        <li key={todo.id}>{todo.title}</li>      ))}    </ul>  );}export default TodoList;

在此代码中,我们使用 useContext 挂钩从 TodoContext 检索 TodoService。 然后我们使用检索到的 todoService 来获取 todos。KC628资讯网——每日最新资讯28at.com

useEffect 钩子用于在组件安装时获取待办事项。 fetchTodos 函数使用检索到的 todoService 来检索 todos 并将它们设置为 todos 状态变量。KC628资讯网——每日最新资讯28at.com

要使用此组件,我们首先创建一个 TodoContext 并将组件包装在其中,如下所示:KC628资讯网——每日最新资讯28at.com

import React from 'react';import TodoContext from './TodoContext';import TodoService from './TodoService';import TodoList from './TodoList';function App() {  return (    <TodoContext.Provider value={TodoService}>      <TodoList />    </TodoContext.Provider>  );}export default App;

在此示例中,我们创建一个 TodoContext 并将 TodoService 作为其值传递。 然后,我们将 TodoList 组件包装在 TodoContext.Provider 组件内,以便 TodoList 组件可以使用 useContext 挂钩从上下文中检索 TodoService。KC628资讯网——每日最新资讯28at.com

使用控制反转容器 (IOC) 进行依赖注入

使用这个上下文概念,我们可以再采取一步,使用控制反转容器。KC628资讯网——每日最新资讯28at.com

等等,什么是控制反转容器 (IoC)?KC628资讯网——每日最新资讯28at.com

在 React 中,IoC(控制反转)容器是一种工具,可让您管理应用程序中不同组件和服务之间的依赖关系。 它提供了一种方法来定义和注册服务或对象(依赖项)一次,然后将它们注入到依赖它们的其他组件中。 这有助于解耦组件,并使您的应用程序更加模块化且更易于维护。KC628资讯网——每日最新资讯28at.com

React 中的 IoC 容器通常通过提供一个中央注册表来工作,该注册表引用可用作依赖项的所有对象。 组件可以从容器请求这些依赖项,而不是直接创建它们。 这种方法还可以轻松地用替代实现替换依赖项或模拟它们进行测试。KC628资讯网——每日最新资讯28at.com

React 有几种流行的 IoC 容器,例如 InversifyJS、Awilix 和 BottleJS,它们提供了构造函数注入、属性注入和自动依赖解析等各种功能。 一些 IoC 容器比其他容器更复杂,因此选择适合您的项目需求和复杂程度的容器非常重要。KC628资讯网——每日最新资讯28at.com

在我们的例子中,我们将从头开始编写一个示例,如下所示:KC628资讯网——每日最新资讯28at.com

import React, { createContext, useContext } from 'react';// Create a new context for the containerconst ContainerContext = createContext();// Define a component that provides the container to its childrenconst ContainerProvider = ({ container, children }) => {  return <ContainerContext.Provider value={container}>{children}</ContainerContext.Provider>;};// Define a hook to access the container from within a componentconst useContainer = () => {  const container = useContext(ContainerContext);  if (!container) {    throw new Error('Container not found. Make sure to wrap your components with a ContainerProvider.');  }  return container;};// Define a hook to inject dependencies from the containerconst useInject = (identifier) => {  const container = useContainer();  return container.resolve(identifier);};// Example usage:const MyService = () => {  return { foo: 'bar' };};const MyComponent = () => {  const myService = useInject('myService');  return <div>{myService.foo}</div>; // Output: 'bar'};const container = {  registry: {    myService: MyService()  },  resolve(identifier) {    if (!this.registry.hasOwnProperty(identifier)) {      throw new Error(`Object with identifier ${identifier} not found in container`);    }    return this.registry[identifier];  }};const App = () => {  return (    <ContainerProvider container={container}>      <MyComponent />    </ContainerProvider>  );};

在此示例中,我们创建一个 ContainerProvider 组件,该组件将容器对象作为 prop,并使用 ContainerContext 上下文将其提供给其子组件。 我们还定义了一个 useContainer 钩子,可用于从组件内检索容器。KC628资讯网——每日最新资讯28at.com

然后,我们定义一个 MyService 对象并将其添加到容器对象的注册表属性中。 我们还在容器对象上定义了一个解析方法,该方法采用标识符并从注册表中检索相应的对象。 在本例中,resolve 方法返回 MyService 对象。KC628资讯网——每日最新资讯28at.com

我们用 ContainerProvider 包装 MyComponent,并将容器对象作为 prop 传入,然后渲染 App 组件,该组件渲染用 ContainerProvider 包装的 MyComponent。 当呈现 MyComponent 时,它会从容器中检索 myService 依赖项,并将其 foo 属性呈现到屏幕上。KC628资讯网——每日最新资讯28at.com

在此代码中,我们添加了一个 useInject 挂钩,该挂钩将标识符作为参数并从容器中检索相应的对象。 useInject 钩子在内部调用 useContainer 来检索容器,然后调用容器上的resolve 方法来检索对象。KC628资讯网——每日最新资讯28at.com

接下来,我们创建一个 MyComponent,它使用 useInject 挂钩从容器中检索 myService 依赖项,并将其 foo 属性呈现到屏幕上。KC628资讯网——每日最新资讯28at.com

最后,我们渲染 App 组件,它渲染用 ContainerProvider 包装的 MyComponent。 当呈现 MyComponent 时,它使用 useInject 挂钩从容器中检索 myService 依赖项,并将其 foo 属性呈现到屏幕上。KC628资讯网——每日最新资讯28at.com

总之,依赖注入是一种设计模式,它允许更灵活、模块化且易于测试的代码。 它将对象的创建与其使用分开,使组件之间的依赖关系变得明确并促进复杂依赖关系的管理。KC628资讯网——每日最新资讯28at.com

在 React 中,依赖注入可以通过将服务作为 props 注入或使用容器通过钩子为组件提供依赖关系来实现。 这种做法可以使代码更清晰、更易于维护,从而更容易重用业务逻辑和管理依赖项。KC628资讯网——每日最新资讯28at.com

遵循此模式可以提高 React 代码的可读性、可维护性和可测试性。KC628资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-11735-0.htmlReact中的依赖注入,看这一篇就够了!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: @Transactional注解使用以及事务失效的场景

下一篇: Java中数据共享和同步问题,导致线程安全性问题和竞态条件

标签:
  • 热门焦点
  • K8S | Service服务发现

    一、背景在微服务架构中,这里以开发环境「Dev」为基础来描述,在K8S集群中通常会开放:路由网关、注册中心、配置中心等相关服务,可以被集群外部访问;图片对于测试「Tes」环境或者
  • 使用LLM插件从命令行访问Llama 2

    最近的一个大新闻是Meta AI推出了新的开源授权的大型语言模型Llama 2。这是一项非常重要的进展:Llama 2可免费用于研究和商业用途。(几小时前,swyy发现它已从LLaMA 2更名为Lla
  • 一文掌握 Golang 模糊测试(Fuzz Testing)

    模糊测试(Fuzz Testing)模糊测试(Fuzz Testing)是通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。可以用来发现应用程序、操作系统和网络协议等中的漏洞或
  • 破圈是B站头上的紧箍咒

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之每年的暑期档都少不了瞄准追剧女孩们的古偶剧集,2021年有优酷的《山河令》,2022年有爱奇艺的《苍兰诀》,今年却轮到小破站抓住了追
  • 东方甄选单飞:有些鸟注定是关不住的

    作者:彭宽鸿来源:华尔街科技眼&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;东方甄选创始人俞敏洪带队的&ldquo;7天甘肃行&rdquo;直播活动已在近日顺利收官。成立后一
  • 小米MIX Fold 3配置细节曝光:搭载领先版骁龙8 Gen2+罕见5倍长焦

    这段时间以来,包括三星、一加、荣耀等等有不少品牌旗下的最新折叠屏旗舰都得到了不少爆料,而小米新一代折叠屏旗舰——小米MIX Fold 3此前也屡屡被传
  • 三星折叠屏手机去年销售近1000万台 今年目标定为1500万

    7月29日消息,三星率先发力可折叠手机市场,在全球市场已经取得了非常亮眼的成绩,接下来会进一步巩固和扩大这一优势。三星在推出Galaxy Z Flip5和Galax
  • 超级标准版旗舰!iQOO 11S全球首发iQOO超算独显芯片

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
  • 上海举办人工智能大会活动,建设人工智能新高地

    人工智能大会在上海浦江两岸隆重拉开帷幕,人工智能新技术、新产品、新应用、新理念集中亮相。8月30日晚,作为大会的特色活动之一的上海人工智能发展盛典人工
Top