了解 React Clean Architecture 如何帮助 React 开发人员编写干净、结构化、模块化和最佳编码实践

650 阅读5分钟

了解 React Clean Architecture 如何帮助 React 开发人员编写干净、结构化、模块化和最佳编码实践。

图片

开发者您好! 我们中的许多人在 React 开发中使用各种设计模式来使 React 应用程序更干净、更清晰易懂且更结构化。 但是我们仍然面临编码标准的问题,我们在一个地方改变了,它在另一个地方崩溃了。 有什么解决办法吗? 是的,试试 React Clean Architecture!

快速亮点 — React Clean Architecture — 这使您的代码更加结构化、干净,任何人都可以轻松接管您的代码并开始与您合作。 那么让我们继续下一步。 其中包括所有 API、状态管理(Redux、Redux Saga)、 Storybook 、实用工具、组件/容器,您可以在定义的结构层次结构中添加更多相关功能。

下载 React Clean Architecture 源代码

图案 -

图片

涵盖 React 清洁架构 -

反应清洁架构 
├──安卓 
├── ios 
├── src 
│ ├── 应用 
│ │ ├── 普通 
│ │ ├── 过滤器 
├── │ ├── 记录器 
│ │ ├──模型 
│ │ ├── 坚持 
│ │ ├──插件 
│ │ ├──商店 
│ ├──基础设施 
│ │ ├── api(服务) 
│ │ ├── components(常用组件) 
│ ├── 介绍 
│ │ ├──容器 
│ │ ├──组件 
├── index.js 
├── package.json 
└── README.md 

应用 -

应用程序目录包含状态管理和通用实用程序函数和常量。 对于状态管理——我使用过 Redux Rematch,你可以使用 Redux、Redux Saga、 MobX 状态管理 。 对于通用——我使用了字体、颜色、全局常量和通用函数。

让我们检查 Rematch 的某些部分并了解它的作用和含义。

店铺 -

# 存储/index.js 

从“@rematch/core”导入{初始化}; 
从“redux-logger”导入记录器; 

从 '../models' 导入 * 作为模型; 
从'../plugins'导入{loadingPlugin}; 
从'../persist'导入{persistPlugin}; 

导出默认初始化({ 
楷模, 
插件:[loadingPlugin,persistPlugin], 
还原:{ 
中间件:[记录器], 
  }, 
}); 

在这里,我初始化 Redux Store,为了初始化 Redux Store,我们需要模型、插件、中间件(可选)。

插件 -

PlugIns 本身意味着为 Redux Store 添加一些值。这里,我们使用 Loading PlugIns 意味着它会在 API 获取数据时显示加载指示器。 所以我们可以向用户显示加载器,一旦获取数据加载插件更新加载状态,并基于此我们可以隐藏组件中的加载器。

从“@rematch/loading”导入 createLoadingPlugin; 

导出 const loadingPlugin = createLoadingPlugin({ 
白名单:['ToDo / fetchTasks'], 
}); 

坚持——

Persist 本身就是 Persist 的意思,这里就是将 Rematch Store 持久化。 要创建持久存储,它将需要一些参数、密钥、白名单(模型 — 保存在持久存储中)、黑名单(模型 — 未保存在持久存储中)、版本 — 升级应用程序时的帮助、存储 — AsyncStorage(将持久存储存储在 AsyncStorage 中) , transform — contains — 在持久存储时应用的过滤器。

从“@react-native-community/async-storage”导入 AsyncStorage; 
从“@rematch/persist”导入 createRematchPersist; 
从 '../filters' 导入 { AllFilters }; 

导出 const persistPlugin = createRematchPersist({ 
键:'根', 
白名单:['待办事项'], 
版本:1, 
存储:异步存储, 
转换:所有过滤器, 
}); 

楷模 -

模型将包含状态、减速器、效果(动作)。

从'../../infrastructure/api/api'导入{列表}; 
导出 const 待办事项 = { 
状态: { 
arrTasks: [], 
arrAPITasks: [], 
总任务数:3, 
  }, 
减速器:{ 
setTasks(状态,有效载荷){ 
返回 { 
...状态, 
arrTasks:有效载荷, 
      }; 
    }, 
setAPITasks(状态,有效载荷){ 
返回 { 
...状态, 
arrAPITasks:有效载荷, 
      }; 
    }, 
清除() { 
返回 { 
arr受益人:[], 
      }; 
    }, 
  }, 
效果:(调度)=>({ 
异步 fetchTasks() { 
尝试 { 
dispatch.ToDo.setTasks ([ 
            { 
任务ID:1, 
任务名称:'任务#1', 
            } 
        ]); 
} 捕捉(错误){ 
      } 
    }, 
异步 fetchTasksFromServer() { 
尝试 { 
const response = await List.getListData().toPromise(); 
dispatch.ToDo.setAPITasks(response); 
} 捕捉(错误){ 
      } 
    }, 
  }), 
}; 

过滤器 -

import { createBlacklistFilter } from 'redux-persist-transform-filter'; 

const toDoFilter = createBlacklistFilter('ToDo', ['totalTasks']); 

导出 const AllFilters = [toDoFilter]; 

常见的 -

在这里,您可以根据自定义解决方案定义全局常量、通用文件 — 字体、字体大小、设备规范、颜色等。

出口.globalVars = { 
用户盐:'TOHV7eOQRAXmbe433BilgtJeCkugs1rgvZ', 
当前国家代码:'', 
}; 
export const BaseURL = "https://jsonplaceholder.typicode.com/"; 
export const TaskList = 'todos/'; 
导出 const apiVersion = '事件/'; 
出口 const Authsecret = ''; 
出口 const timeoutDuration = 30000; 

// 错误信息 
export const errorEncountered = '处理此请求时遇到错误'; 
导出常量超时消息 = 
“我们目前无法获取数据,请检查您的互联网连接,我们会重新连接您。”; 

基础设施 -

基础设施包含 API(服务)文件、API 处理程序、通用组件(如加载器、通用文本字段、按钮等)。在这里,我使用了 AXIOS,您可以使用 JavaScript Fetch 并在此处创建您的 API Wrapper 类。

让我们检查基础设施的某些部分并了解它的作用和含义。

API(服务)-

# api/api/List.js'../APIHandler' 导入 APIHandlerimport * as Globals from '../../../application/common/Globals'; 

导出默认{ 
getListData: () => APIHandler.get(Globals.TaskList), 
};# api/api/List.js'../APIHandler' 导入 APIHandlerimport * as Globals from '../../../application/common/Globals'; 

导出默认{ 
getListData: () => APIHandler.get(Globals.TaskList), 
}; 
# api/APIHandler.js'react-native'导入{警报}; 
import { Observable, throwError, from } from 'rxjs'; 
进口 { 
mergeMap、retryWhen、take、delay、catchError、map、 
来自'rxjs/operators'; 
从 'axios' 导入 axios,{AxiosPromise}; 
import * as Globals from '../../application/common/Globals'; 

异步函数 handleRequest(req) { 
const ts = new Date().getTime(); 
req.headers.Accept = 'application/json'; 
req.headers.timestamp = ts; 
返回请求; 
} 

导出默认{ 
post: (url: string, data: any, options?: any) => processApiRequest( 
    axios.post( 
选项&& options.fullPathurl: Globals.BaseURL + url, 
数据, 
{ timeout: Globals.timeoutDuration }, 
选项 && { 标题:选项 }, 
    ), 
  ), 
get: (url: string, options?: any, data?: any) => { 
数据 = 数据?  (data instanceof Object && !Object.keys(data).length ? null : data) : null; 
const 配置 = 数据 
?  { 标题:选项,数据,超时:Globals.timeoutDuration } 
:{ 标题:选项,数据:'',超时:Globals.timeoutDuration }; 
返回进程ApiRequest( 
axios.get(options && options.fullPath ? url : Globals.BaseURL + url, config), 
    ); 
  }, 
}; 

组件(通用组件)-

# 组件/加载器/index.js 

import React, { Component } from 'react'; 
从'react-native'导入{视图,ActivityIndicator}; 
从'./Styles'导入样式; 

功能加载器(道具){ 
const { 加载 } = 道具; 
如果(加载){ 
返回 ( 
<视图样式={Styles.loaderWrapper}> 
<ActivityIndicator size="large" /> 
</查看> 
        )  
} 别的 { 
<查看/> 
    }     
} 

导出默认加载器; 

介绍 -

演示文稿包含组件/容器。 组件返回设计,Container 包含 Component 的包装器,HOC Wrapper Of Connect (Redux) 以使用 Redux Store | 道具到组件中。

让我们检查一下 Component/Container 的某些部分,它的作用和含义。

# 组件/待办事项/index.js 

从“反应”导入反应; 
从'react-native' 导入 { SafeAreaView }; 
从'../../container/ToDo/TaskListContainer'导入TaskListContainer; 
从'./Styles'导入样式; 

功能ToDoManagement(){ 
返回 ( 
<SafeAreaView style={Styles.container}> 
<任务列表容器 /> 
</安全区域视图> 
    ); 
} 

导出默认的 ToDoManagement; 

# 容器 / 待办事项 / TaskListContainer.js'react-redux'导入{连接}; 
从'../../component/ToDo/TaskListComponent'导入TaskListComponentconst mapStateToProps = ({ ToDo, loading }) => ({ 
arrTasks: ToDo.arrTasks, 
加载:loading.effects.ToDo.fetchTasks, 
  }); 
  
const mapDispatchToProps = ({ 
一切: { 
获取任务, 
fetchTasksFromServer, 
      }  
}) => ({ 
fetchTasks: () => fetchTasks(), 
fetchTasksFromServer: () => fetchTasksFromServer() 
  }); 
  
导出默认连接(mapStateToProps,mapDispatchToProps)(TaskListComponent); 

# 组件/待办事项/TaskListComponent.js 

import React, { useEffect } from 'react'; 
导入 { SafeAreaView, FlatList } from 'react-native'; 
从'../../container/ToDo/TaskItemContainer'导入TaskItemContainer; 

功能任务列表组件(道具){ 
useEffect(() => { 
props.fetchTasks(); 
props.fetchTasksFromServer(); 
    }, []) 
返回 ( 
<平面列表 
数据={props.arrTasks} 
renderItem={({ item, index }) => 
<任务项目容器 
{...物品} 
/>} 
/> 
    ); 
} 

导出默认任务列表组件;