React抽象实践:HOC与hooks的局限?批量资源表单复用困境
解决方案
1. 利用React Query的enabled选项规避条件调用问题
react-query的useQuery支持enabled配置项,可控制查询是否执行。无需条件调用useGetResource,直接在组件顶层调用它,同时根据id的值设置enabled: !!id——这样既符合Hook的调用规则(顶层无条件调用),又能在创建场景下跳过获取数据的请求:
// 通用表单组件 const ResourceForm = ({ resourceConfig, id }) => { // 无条件调用查询Hook,用enabled控制是否执行请求 const { data: initialData } = resourceConfig.useGetResource(id, { enabled: !!id, }); // 根据id选择创建/更新的mutation Hook const { mutate: submitResource, isLoading } = id ? resourceConfig.useUpdateResource() : resourceConfig.useCreateResource(); // 初始化表单数据:更新场景用接口返回值,创建场景用默认空值 const formInitialData = initialData || resourceConfig.defaultInitialData; // 表单提交逻辑 const handleSubmit = (values) => { submitResource(values); }; return ( <Form initialValues={formInitialData} onSubmit={handleSubmit} fields={resourceConfig.fields} /> ); }; // 食谱资源的配置对象(新增资源仅需新增此类配置) const recipeConfig = { useGetResource: (id, options) => useQuery(['recipe', id], () => fetchRecipe(id), options), useCreateResource: () => useMutation((data) => createRecipe(data)), useUpdateResource: () => useMutation((data) => updateRecipe(data)), defaultInitialData: { title: '', ingredients: [] }, fields: [ { name: 'title', label: '食谱标题' }, { name: 'ingredients', label: '食材', type: 'textarea' }, // 其他字段定义... ] }; // 使用示例 // 创建表单 <ResourceForm resourceConfig={recipeConfig} /> // 更新表单 <ResourceForm resourceConfig={recipeConfig} id={recipeId} />
2. 封装通用Hook统一处理初始数据
若不想在组件中直接处理enabled逻辑,可封装专门的Hook统一管理创建/更新场景的初始数据:
const useFormInitialData = (useGetResource, id, defaultData) => { const { data } = useGetResource(id, { enabled: !!id }); return data || defaultData; }; // 在通用表单组件中使用 const ResourceForm = ({ resourceConfig, id }) => { const initialData = useFormInitialData(resourceConfig.useGetResource, id, resourceConfig.defaultInitialData); const { mutate: submitResource, isLoading } = id ? resourceConfig.useUpdateResource() : resourceConfig.useCreateResource(); // 后续表单渲染逻辑... };
3. 配置化+组件组合最大化复用
把每个资源的所有差异(接口Hook、字段定义、默认初始值、提交回调等)都抽成配置对象,新增资源时仅需编写对应配置,无需重复编写表单组件。甚至可以封装通用字段渲染组件,根据fields配置自动生成表单项,彻底消除UI层重复代码。
内容的提问来源于stack exchange,提问作者mclslee
相关产品推荐
相关产品推荐

