为了确保在组件的第一次 render 时 useForm 的 defaultValues 能够拿到来自 store 的值,可以提前将 store 中的数据加载完毕后再初始化表单。以下是几种方法:
方法一:在父组件中提前加载数据
在组件挂载前通过父组件或其他逻辑提前从 store 中获取数据,并将其作为 props 传递给表单组件,这样可以确保表单组件在第一次 render 时已经有了所需的 defaultValues。
import React, { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useStore } from './store';
function MyForm({ initialData }) {
const { register } = useForm({
defaultValues: initialData, // 将从父组件传递的初始数据作为 defaultValues
});
return (
<form>
<input {...register("field1")} />
<input {...register("field2")} />
{/* 其他表单字段 */}
</form>
);
}
function ParentComponent() {
const data = useStore(state => state.data);
if (!data) return <div>Loading...</div>; // 确保数据在渲染表单前已经加载完毕
return <MyForm initialData={data} />;
}
方法二:在组件内部提前加载数据
你可以在组件内部使用 useEffect 钩子提前加载数据,并在数据加载完成后再初始化表单。通过将表单的渲染延迟到数据加载完成后,可以确保第一次 render 时 useForm 的 defaultValues 已经有值。
import React, { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useStore } from './store';
function MyForm() {
const [loadedData, setLoadedData] = useState(null);
const { register, reset } = useForm();
const fetchData = useStore(state => state.fetchData);
useEffect(() => {
// 假设 fetchData 是一个异步函数,负责从 API 或 store 加载数据
const loadInitialData = async () => {
const data = await fetchData();
setLoadedData(data);
reset(data); // 数据加载后重置表单
};
loadInitialData();
}, [fetchData, reset]);
if (!loadedData) return <div>Loading...</div>; // 数据加载前显示加载状态
return (
<form>
<input {...register("field1")} />
<input {...register("field2")} />
{/* 其他表单字段 */}
</form>
);
}
这里是一个使用 zustand 创建的 fetchData 方法示例,用于从 API 或其他数据源加载数据并存储在 zustand 的状态中。
zustand Store 示例
import create from 'zustand';
import axios from 'axios'; // 用于发起 HTTP 请求的库,可以根据需要替换为其他库
const useStore = create((set) => ({
data: null, // 用于存储数据的初始状态
// fetchData 是一个异步函数,用于从 API 加载数据并更新状态
fetchData: async () => {
try {
const response = await axios.get('/api/endpoint'); // 替换为你的 API 端点
const data = response.data;
set({ data }); // 将数据存储到 Zustand 状态中
return data; // 返回数据,方便在调用方处理
} catch (error) {
console.error('Failed to fetch data:', error);
return null; // 错误处理,返回 null 或者其他默认值
}
},
}));
export default useStore;
在组件中使用 fetchData
使用上面的 useStore 中的 fetchData 函数,你可以在组件中调用它来获取数据并更新表单的默认值:
import React, { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import useStore from './store'; // 引入刚刚创建的 Zustand store
function MyForm() {
const [loadedData, setLoadedData] = useState(null);
const { register, reset } = useForm();
const fetchData = useStore(state => state.fetchData);
useEffect(() => {
// 使用 store 中的 fetchData 函数获取数据
const loadInitialData = async () => {
const data = await fetchData();
setLoadedData(data);
if (data) {
reset(data); // 数据加载后重置表单
}
};
loadInitialData();
}, [fetchData, reset]);
if (!loadedData) return <div>Loading...</div>; // 数据加载前显示加载状态
return (
<form>
<input {...register("field1")} />
<input {...register("field2")} />
{/* 其他表单字段 */}
</form>
);
}
export default MyForm;
详细说明
-
zustandStore:- 创建了一个
useStore的zustandstore,其中包含一个data状态和一个fetchData异步函数。 fetchData函数使用axios从指定的 API 端点获取数据,并使用set更新zustand的data状态。
- 创建了一个
-
组件中的使用:
- 在组件中使用
useEffect钩子调用fetchData函数以加载初始数据。 - 在数据加载完成后,使用
reset方法更新react-hook-form表单的默认值。
- 在组件中使用
-
异步加载和更新:
fetchData函数在后台异步获取数据。数据加载完成后,表单会使用获取到的数据更新默认值,从而确保用户在第一次交互时看到的是最新的数据。
这个示例展示了如何通过 zustand 的 store 来管理 API 数据获取和表单状态的同步。如果需要处理更复杂的情况,比如错误处理或加载状态,亦可在 useEffect 中添加更多逻辑。
方法三:使用 useForm 的 defaultValues 动态初始化
在 useForm 初始化时直接使用 zustand store 中的状态,如果数据可能为 null 或未定义,你可以在初始化时提供一个默认值。
import React from 'react';
import { useForm } from 'react-hook-form';
import { useStore } from './store';
function MyForm() {
const data = useStore(state => state.data);
const { register } = useForm({
defaultValues: data || { field1: '', field2: '' }, // 设置默认值,防止第一次渲染时为 undefined
});
if (!data) return <div>Loading...</div>;
return (
<form>
<input {...register("field1")} />
<input {...register("field2")} />
{/* 其他表单字段 */}
</form>
);
}
总结
- 提前加载数据:通过父组件或在组件内部提前加载数据,以确保在表单组件初始化时已经有了
defaultValues。 - 动态初始化:使用条件判断在初始化时提供一个默认值,以避免
defaultValues在第一次渲染时为空。
这几种方法都可以确保 defaultValues 在第一次渲染时有值,你可以根据具体需求选择合适的方案。
写作不易,如果觉得对你有用,请点个赞赞👍🏻, 感谢支持~~