react-jsonschema-form与React Query查询依赖管理
【免费下载链接】react-jsonschema-form 项目地址: https://gitcode.***/gh_mirrors/rea/react-jsonschema-form
你是否在构建表单时遇到过数据依赖复杂、加载状态难以同步的问题?本文将介绍如何通过react-jsonschema-form与React Query的组合,优雅解决表单查询依赖管理难题。读完本文,你将掌握动态表单数据加载、查询状态与表单状态协同、依赖缓存优化等核心技能。
场景痛点与解决方案
在企业级应用中,表单往往需要根据后端数据动态生成选项。例如:
- 省份选择后加载对应城市列表
- 产品类别变更时刷新规格选项
- 用户权限不同显示差异化表单字段
传统解决方案存在以下问题:
- 组件内混杂数据请求与表单逻辑,代码臃肿
- 加载状态与表单状态同步困难,用户体验差
- 重复请求未缓存,性能损耗严重
react-jsonschema-form(以下简称RJSF)提供了基于JSON Schema的声明式表单构建能力,而React Query专注于数据请求状态管理。两者结合可实现:
- 表单结构与数据获取解耦
- 自动处理加载/错误状态
- 智能缓存与请求去重
技术架构与工作流
表单与查询协同架构
核心架构包含三个层次:
- 数据层:React Query管理API请求与缓存
- 适配层:自定义RJSF组件连接查询结果
- 表现层:RJSF渲染表单并处理用户交互
工作流程如下:
快速实现步骤
1. 安装与基础配置
首先安装必要依赖:
npm install @rjsf/core @rjsf/utils react-query axios
配置React Query客户端(src/utils/react-query.ts):
import { QueryClient, QueryClientProvider } from 'react-query';
// 创建查询客户端实例
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 数据5分钟内视为新鲜
retry: 1, // 失败时重试1次
refetchOnWindowFocus: false, // 窗口聚焦不重新获取
},
},
});
export { QueryClientProvider, queryClient };
2. 创建查询增强型Widget
实现一个支持异步加载选项的SelectWidget(src/widgets/AsyncSelectWidget.tsx):
import React from 'react';
import { useQuery } from 'react-query';
import { SelectWidget } from '@rjsf/core';
import axios from 'axios';
// 定义查询函数
const fetchOptions = async (url) => {
const { data } = await axios.get(url);
return data.map(item => ({
label: item.name,
value: item.id
}));
};
// 异步选择组件
export const AsyncSelectWidget = ({
options,
onChange,
...props
}) => {
const { url, dependencies } = options;
// 使用React Query获取数据
const { data: asyncOptions, isLoading, error } = useQuery(
['dynamic-options', url, dependencies],
() => fetchOptions(url),
{
enabled: !!url && dependencies.every(dep => dep.value !== undefined),
}
);
return (
<SelectWidget
{...props}
options={asyncOptions || []}
onChange={onChange}
disabled={isLoading || props.disabled}
/>
);
};
3. 注册自定义Widget
配置RJSF注册表(src/utils/rjsf-registry.ts):
import { getDefaultRegistry } from '@rjsf/core';
import { AsyncSelectWidget } from '../widgets/AsyncSelectWidget';
const registry = getDefaultRegistry();
// 注册自定义Widget
registry.widgets.select = AsyncSelectWidget;
export default registry;
4. 定义依赖型JSON Schema
创建包含查询依赖的表单Schema(src/schemas/location-form.json):
{
"type": "object",
"properties": {
"province": {
"type": "string",
"title": "省份",
"enum": ["zj", "gd", "bj"],
"enumNames": ["浙江", "广东", "北京"]
},
"city": {
"type": "string",
"title": "城市",
"ui:widget": "select",
"ui:options": {
"url": "/api/cities?province={province}",
"dependencies": ["province"]
}
}
}
}
5. 组合表单与查询
实现完整表单组件(src/***ponents/LocationForm.tsx):
import React from 'react';
import { Form } from '@rjsf/core';
import { QueryClientProvider, useQueryClient } from 'react-query';
import registry from '../utils/rjsf-registry';
import locationSchema from '../schemas/location-form.json';
import { queryClient } from '../utils/react-query';
export const LocationForm = () => {
const handleSubmit = (data) => {
console.log('表单数据:', data.formData);
};
return (
<QueryClientProvider client={queryClient}>
<Form
schema={locationSchema}
registry={registry}
onSubmit={handleSubmit}
liveValidate
/>
</QueryClientProvider>
);
};
高级优化策略
查询失效与数据刷新
当依赖字段变化时,需要主动失效相关查询:
// 在自定义Widget中监听依赖变化
useEffect(() => {
if (dependenciesChanged) {
queryClient.invalidateQueries(['dynamic-options', url, dependencies]);
}
}, [dependencies, queryClient, url]);
表单状态与查询数据同步
使用RJSF的formData作为查询参数时,需处理初始值情况:
// 在useQuery中使用formData作为查询键
const { data } = useQuery(
['cities', formData.province],
() => fetchCities(formData.province),
{ enabled: !!formData.province }
);
错误处理与重试机制
增强Widget的错误处理能力:
{error && (
<div className="error-message">
<span>加载失败:</span>
<button onClick={() => refetch()}>重试</button>
</div>
)}
性能监控与调试
React Query提供了强大的开发工具(src/App.tsx):
import { ReactQueryDevtools } from 'react-query/devtools';
function App() {
return (
<>
<LocationForm />
<ReactQueryDevtools initialIsOpen={false} />
</>
);
}
通过开发工具可以:
- 查看查询缓存状态
- 跟踪请求性能
- 模拟加载/错误状态
- 手动触发查询刷新
常见问题解决方案
| 问题场景 | 解决方案 | 代码参考 |
|---|---|---|
| 依赖循环引用 | 使用enabled选项控制查询执行时机 |
{ enabled: !!dependencies[0] } |
| 大数据集加载缓慢 | 实现虚拟滚动选项列表 | react-window |
| 表单重置后查询残留 | 重置时清除相关查询缓存 | queryClient.removeQueries(['dynamic-options']) |
| 并发请求冲突 | 使用查询取消机制 | signal: abortController.signal |
最佳实践总结
-
查询封装:将API请求封装为自定义hooks,如
useCities(province) -
缓存策略:根据数据特性设置合理的
staleTime和cacheTime - 错误边界:为表单组件添加错误边界,防止查询失败导致崩溃
-
加载状态:使用RJSF的
ui:options传递加载状态到表单模板 - 查询去重:利用React Query自动去重相同请求,减少网络开销
扩展应用场景
- 级联选择:实现省市区三级联动
- 权限控制:根据用户角色动态加载表单字段
- 数据验证:使用React Query进行异步表单验证
- 批量操作:结合useMutation实现表单数据批量提交
通过react-jsonschema-form与React Query的组合,我们可以构建出既灵活又高性能的动态表单系统。这种架构不仅分离了关注点,还提供了优秀的用户体验和开发效率。
点赞收藏本文,关注作者获取更多RJSF高级实践技巧!下一期我们将探讨如何实现复杂表单的分步提交与查询事务管理。
【免费下载链接】react-jsonschema-form 项目地址: https://gitcode.***/gh_mirrors/rea/react-jsonschema-form