React Clean Architecture
React Clean Architecture 涵盖 -
应用 -
基础设施 -
推介会 -
各位开发者们,大家好!我们许多人在 React 开发中使用各种设计模式,以使 React 应用更简洁、更易理解、更结构化。但我们仍然面临编码规范的问题,我们修改了一个地方,另一个地方就崩溃了。有解决办法吗?有的,试试 React 简洁架构吧!
快速亮点- React 简洁架构 - 让你的代码更加结构化、简洁,任何人都可以轻松接管你的代码并开始与你合作。接下来我们继续。它涵盖了所有 API、状态管理(Redux、Redux Saga)、Storybook、实用程序、组件/容器,并且你可以在定义的结构层次结构中添加更多相关功能。
React Clean Architecture 涵盖 -
react-clean-architecture
├── android
├── ios
├── src
│ ├── application
│ │ ├── common
│ │ ├── filters
│ │ ├── logger
│ │ ├── models
│ │ ├── persist
│ │ ├── plugins
│ │ ├── store
│ ├── infrastructure
│ │ ├── api(services)
│ │ ├── components (common components)
│ ├── presentation
│ │ ├── container
│ │ ├── component
├── index.js
├── package.json
└── README.md
应用 -
应用程序目录包含状态管理和常用实用程序函数及常量。对于状态管理,我使用了 Redux Rematch,您也可以使用 Redux、Redux Saga 和MobX状态管理。对于常用功能,我使用了字体、颜色、全局常量和常用函数。
让我们检查一下 Rematch 的一些部分并了解它的作用和含义。
店铺 -
# Store/index.js
import { init } from '@rematch/core';
import logger from 'redux-logger';
import * as models from '../models';
import { loadingPlugin } from '../plugins';
import { persistPlugin } from '../persist';
export default init({
models,
plugins: [loadingPlugin, persistPlugin],
redux: {
middlewares: [logger],
},
});
在这里,我初始化 Redux Store,要初始化 Redux Store 我们需要模型、插件、中间件(可选)。
插件 -
PlugIns 本身意味着为 Redux Store 增添一些价值。这里我们使用了 Loading PlugIns,这意味着它会在 API 获取数据时显示加载指示器。因此,我们可以向用户显示 Loader,一旦数据获取完成,Loading 插件就会更新加载状态,并基于此隐藏组件中的 Loader。
import createLoadingPlugin from '@rematch/loading';
export const loadingPlugin = createLoadingPlugin({
whitelist: ['ToDo/fetchTasks'],
});
持续存在 -
Persist 本身就是持久化某些东西,在这里,它将持久化到 Rematch Store。创建持久化存储需要几个参数:键、白名单(模型 - 保存在持久化存储中)、黑名单(模型 - 不保存在持久化存储中)、版本 - 升级应用程序时的帮助信息、存储 - AsyncStorage(将持久化存储存储在 AsyncStorage 中)、转换 - 包含 - 持久化存储时应用的过滤器。
import AsyncStorage from '@react-native-community/async-storage';
import createRematchPersist from '@rematch/persist';
import { AllFilters } from '../filters';
export const persistPlugin = createRematchPersist({
key: 'root',
whitelist: ['ToDo'],
version: 1,
storage: AsyncStorage,
transforms: AllFilters,
});
模型 -
模型将包含状态、Reducer、效果(动作)。
import { List } from '../../infrastructure/api/api';
export const ToDo = {
state: {
arrTasks: [],
arrAPITasks: [],
totalTasks: 3,
},
reducers: {
setTasks(state, payload) {
return {
...state,
arrTasks: payload,
};
},
setAPITasks(state, payload) {
return {
...state,
arrAPITasks: payload,
};
},
clear() {
return {
arrBeneficiary: [],
};
},
},
effects: (dispatch) => ({
async fetchTasks() {
try {
dispatch.ToDo.setTasks([
{
taskID: 1,
taskName: 'Task #1',
}
]);
} catch (error) {
}
},
async fetchTasksFromServer() {
try {
const response = await List.getListData().toPromise();
dispatch.ToDo.setAPITasks(response);
} catch (error) {
}
},
}),
};
过滤器 -
import { createBlacklistFilter } from 'redux-persist-transform-filter';
const toDoFilter = createBlacklistFilter('ToDo', ['totalTasks']);
export const AllFilters = [toDoFilter];
常见的 -
在这里,您可以根据自定义解决方案定义全局常量、通用文件 - 字体、字体大小、设备规格、颜色等等。
exports.globalVars = {
userSalt: 'TOHV7eOQRAXmbe433BilgtJeCkugs1rgvZ',
currentCountryCode: '',
};
export const BaseURL = "https://jsonplaceholder.typicode.com/";
export const TaskList = 'todos/';
export const apiVersion = 'events/';
export const Authsecret = '';
export const timeoutDuration = 30000;
// Error Messages
export const errorEncountered = 'Error was encountered processing this request';
export const timeoutMessage =
"We are unable to fetch data at this time, kindly check your internet connection and we'll reconnect you.";
基础设施 -
基础设施包含 API(服务)文件、API 处理程序、通用组件(如加载器、通用文本字段、按钮等)。在这里,我使用了 AXIOS,您可以使用 JavaScript Fetch 并在此处创建您的 API 包装器类。
让我们检查一下基础设施的一些部分,并了解它的作用和含义。
了解更多关于 -零捆绑包大小 - React 服务器组件
API(服务) -
# api/api/List.js
import APIHandler from '../APIHandler';
import * as Globals from '../../../application/common/Globals';
export default {
getListData: () => APIHandler.get(Globals.TaskList),
};
# api/APIHandler.js
import { Alert } from 'react-native';
import { Observable, throwError, from } from 'rxjs';
import {
mergeMap, retryWhen, take, delay, catchError, map,
} from 'rxjs/operators';
import axios, { AxiosPromise } from 'axios';
import * as Globals from '../../application/common/Globals';
async function handleRequest(req) {
const ts = new Date().getTime();
req.headers.Accept = 'application/json';
req.headers.timestamp = ts;
return req;
}
export default {
post: (url: string, data: any, options?: any) => processApiRequest(
axios.post(
options && options.fullPath ? url : Globals.BaseURL + url,
data,
{ timeout: Globals.timeoutDuration },
options && { headers: options },
),
),
get: (url: string, options?: any, data?: any) => {
data = data ? (data instanceof Object && !Object.keys(data).length ? null : data) : null;
const config = data
? { headers: options, data, timeout: Globals.timeoutDuration }
: { headers: options, data: '', timeout: Globals.timeoutDuration };
return processApiRequest(
axios.get(options && options.fullPath ? url : Globals.BaseURL + url, config),
);
},
};
组件(通用组件) -
# components/Loader/index.js
import React, { Component } from 'react';
import { View, ActivityIndicator } from 'react-native';
import Styles from './Styles';
function Loader(props) {
const { loading } = props;
if (loading) {
return (
<View style={Styles.loaderWrapper}>
<ActivityIndicator size="large" />
</View>
)
} else {
<View />
}
}
export default Loader;
推介会 -
演示包含组件/容器。组件返回组件的设计,而容器包含组件的包装器,而 HOC Wrapper Of Connect(Redux)则使用 Redux Store | Props 将其连接到组件中。
让我们检查一下组件/容器的某些部分,它的作用和含义。
容器/组件 -
# component/ToDo/index.js
import React from 'react';
import { SafeAreaView } from 'react-native';
import TaskListContainer from '../../container/ToDo/TaskListContainer';
import Styles from './Styles';
function ToDoManagement() {
return (
<SafeAreaView style={Styles.container}>
<TaskListContainer />
</SafeAreaView>
);
}
export default ToDoManagement;
# container/ToDo/TaskListContainer.js
import { connect } from 'react-redux';
import TaskListComponent from '../../component/ToDo/TaskListComponent';
const mapStateToProps = ({ ToDo, loading }) => ({
arrTasks: ToDo.arrTasks,
loading: loading.effects.ToDo.fetchTasks,
});
const mapDispatchToProps = ({
ToDo: {
fetchTasks,
fetchTasksFromServer,
}
}) => ({
fetchTasks: () => fetchTasks(),
fetchTasksFromServer: () => fetchTasksFromServer()
});
export default connect(mapStateToProps, mapDispatchToProps)(TaskListComponent);
# component/ToDo/TaskListComponent.js
import React, { useEffect } from 'react';
import { SafeAreaView, FlatList } from 'react-native';
import TaskItemContainer from '../../container/ToDo/TaskItemContainer';
function TaskListComponent(props) {
useEffect(() => {
props.fetchTasks();
props.fetchTasksFromServer();
}, [])
return (
<FlatList
data={props.arrTasks}
renderItem={({ item, index }) =>
<TaskItemContainer
{...item}
/>}
/>
);
}
export default TaskListComponent;
感谢您阅读本文!
KPITENG | 数字化转型
www.kpiteng.com/blogs | hello@kpiteng.com