前言
在 React 项目开发中,我们不可避免要接触到 状态管理库 和 数据拉取库。比如 Redux + React Query、MobX + SWR 、MobX + React Query 等组合。这些库虽然能帮我们解决一些实际中的问题,但解决过程其实并不愉快。你会感受到他们像两个彼此孤立的人,各自忙于各自工作,在工作流程衔接上却缺乏丝滑。本文引入了 Spreado ,给你介绍如何让 MobX 和 React Query 这两个孤僻的人协同合作,实现优雅的配合。
关于 MobX
MobX 是一个状态管理库,它通过运用透明的函数式响应编程使状态管理变得简单和可扩展。
关于 React Query
React Query是一个库,可为任何类型的异步数据提供ReactJS状态管理功能。根据他们的官方文件,React Query为我们提供了诸如“ useQuery”之类的自定义钩子来获取数据。在后台,这些挂钩管理许多事情,例如在初始获取后缓存数据,在后台重新获取数据等。
关于 Spreado
首先,Spreado 并非另一个新的状态管理库或数据拉取库,而是将状态管理库和数据拉取库视为对等依赖(peer dependency)进行的一层易用封装,作用是尽可能简化在 React 组件间传播状态和数据。其次,Spreado 以非侵入的方式兼容当下流行的状态管理库和数据拉取库,让开发者能够继续使用原库的任何中间件和插件,同时保留了直接使用状态管理库或数据拉取库来解决极个别情况的可能性。
Spreado 一共有四个 API,我们只需要了解下面这两个就可以轻松在项目中进行状态管理:
- useSpreadOut - 设置要共享的值
- useSpreadIn - 获取共享的值
举例说明
下面我将用一个查询车辆信息的例子来,来详细展示如何快捷优雅的使用 Spreado 实现 MobX + React Query 集成,进而实现数据共享。
1. 创建项目
npx create-react-app spreado-mobx-react-query
cd spreado-mobx-react-query
npm install --saved mobx react-query spreado
2. 准备后端测试数据。
[{id:1,name:'张三','京A 38920',brand:'本田',color:'蓝色',buyDate:'2020-7-1'},
{id:2,name:'李四','京B 12534',brand:'丰田',color:'红色',buyDate:'2018-6-9'},
{id:3,name:'王五','京C 34563',brand:'福田',color:'黄色',buyDate:'2019-3-21'},
{id:4,name:'赵六','京D 63677',brand:'比亚迪',color:'黑色',buyDate:'2016-4-4'},
{id:5,name:'田七','京E 34264',brand:'长城',color:'粉色',buyDate:'2010-7-18'}]
3. 根据 Spreado - 更简单的代码目录结构 创建新文件,命名为 useCarDataQuery.ts。
export type CarData = {
id: number;
name: string;
license : string;
brand: string;
color: string;
buyDate: string;
};
export const QUERY_KEY = "GET_CAR_INFO";
// 如果传入id,则返回1条数据,否则返回全部数据列表
const request = async (id?: number) => {
const res = await fetch(
'https://www.jisuan.mobi/api/spreado/car?id=' + (id ? `?id=${id}` : ''),
{ method: "GET" }
);
return res.json();
};
// 用来设置共享数据
export function useCarDataQuerySpreadOut(id?: string) {
return useSpreadOut(
QUERY_KEY,
useQuery<CarData[]>([QUERY_KEY, id], () => request(id))
);
}
// 用来获得共享数据
export function useCarDataQuerySpreadIn() {
return useSpreadIn<ReturnType<typeof useCarDataQuerySpreadOut>>(
QUERY_KEY,
{}
);
}
4. 在 ComponentA 组件中,使用上面定义的useCarDataQuery来定义获取参数。
const ComponentA: FC = () => {
const [id, setId] = React.useState<number>();
const { isLoading, isFetching, isError, data, refetch } = useCarDataQuerySpreadOut(id);
return (
<div>
{isLoading && <div>Loading...</div>}
{isFetching && <div>Fetching...</div>}
{isError && <div>Error</div>}
{data && <CarLine data={data} />}
<button onClick={() => refetch()}>刷新</button>
<button onClick={() => setId(id ? id+1 : 1)}>获取id为{id}的车辆信息</button>
</div>
);
};
5. 下面创建另一个组件 ComponentB , 来获取所设置的数据。
const ComponentB = () => {
const { isLoading, isSuccess, data } = useCarDataQuerySpreadIn();
return (
<div>
{isLoading && "LoadingA - - - - - "}
{isSuccess && <CarLine data={data} />}
</div>
);
};
通过 useCarDataQuerySpreadIn 就可以拿到 ComponentA 共享的数据。
由以上的例子,可以看出,在功能的实现过程,你甚至完全不需要了解 MobX 和 React Query 的技术细节,让新手能很快上手实现前端与后台接口的对接。
写在最后
相信你只要具备比较基础的 React 能力的情况下,就能通过例子看出 Spreado 的魅力。它的优点并不是具备强大的功能,而是以一种近乎没有冗余度的方式,将状态管理和数据拉取这种每天都要遇到的问题精简到极致。让你不需要频繁游走于不同的配置文件之间。如果有任何疑问,欢迎到 spreado/issues 留言。如果有时间和兴趣,也可以参与到项目建设中来,具体可以参考开发引导。如果觉得小工具有帮助,请给 GitHub repo react-easier/spreado 点个 ⭐️,这也是我们不断前行的动力 😃。