如何将Formik表单值存入Redux Toolkit并通过redux-persist持久化?
实现Formik表单值的Redux持久化(结合Redux Toolkit与redux-persist)
1. 创建存储表单数据的Redux Slice
先定义一个专门的slice来管理表单值和步骤状态,包含更新表单值的action:
// features/form/formSlice.js import { createSlice } from '@reduxjs/toolkit'; import { FormInitialValues } from '../path/to/your/initialValues'; const formSlice = createSlice({ name: 'form', initialState: { formValues: FormInitialValues, module: 0, // 你已有的步骤模块状态 formStep: 0 // 你已有的步骤状态 }, reducers: { // 合并更新表单值 updateFormValues: (state, action) => { state.formValues = { ...state.formValues, ...action.payload }; }, // 你已有的步骤更新方法 setModule: (state, action) => { state.module = action.payload; }, setFormStep: (state, action) => { state.formStep = action.payload; } } }); export const { updateFormValues, setModule, setFormStep } = formSlice.actions; export default formSlice.reducer;
2. 配置redux-persist持久化表单状态
修改store配置,让form slice被持久化到localStorage:
// store.js import { configureStore } from '@reduxjs/toolkit'; import { persistStore, persistReducer } from 'redux-persist'; import storage from 'redux-persist/lib/storage'; // 默认使用localStorage import formReducer from './features/form/formSlice'; const persistConfig = { key: 'root', storage, whitelist: ['form'] // 仅持久化form模块的状态 }; const persistedReducer = persistReducer(persistConfig, formReducer); export const store = configureStore({ reducer: { form: persistedReducer }, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false // 关闭序列化检查,避免redux-persist触发警告 }) }); export const persistor = persistStore(store);
3. 改造表单组件,同步Formik值与Redux状态
在组件中从Redux读取持久化的表单值作为Formik初始值,并实时同步Formik的输入到Redux:
import { useSelector, useDispatch } from 'react-redux'; import { updateFormValues, setModule, setFormStep } from './features/form/formSlice'; import { useEffect } from 'react'; import { useFormik } from 'formik'; export default function UserDetailsForm() { const dispatch = useDispatch(); // 从Redux获取持久化的表单状态 const { formValues, module, formStep } = useSelector(state => state.form); const isSubmitting = useSelector(state => state.form.isSubmitting); // 按需添加 const formik = useFormik({ initialValues: formValues, // 用Redux中持久化的值作为初始值 validationSchema: FORM_MODULES[module]?.schema[formStep], onSubmit: (values, actions) => { sendFormRequest(values, actions); }, enableReinitialize: true // 当Redux中的formValues变化时,重新初始化Formik }); // 实时同步Formik输入值到Redux useEffect(() => { dispatch(updateFormValues(formik.values)); }, [dispatch, formik.values]); // 替换原有步骤控制方法,直接触发Redux action const handleSetModule = (newModule) => { dispatch(setModule(newModule)); }; const handleSetFormStep = (newStep) => { dispatch(setFormStep(newStep)); }; return ( <form className='form-container' onSubmit={formik.handleSubmit}> {/* 1. Personal Info */} {module === 0 && ( <PersonalInfo formik={formik} formStep={formStep} setFormStep={handleSetFormStep} /> )} {/* 2. Additional Info */} {module === 1 && ( <AdditionalInfo formik={formik} formStep={formStep} setModule={handleSetModule} setFormStep={handleSetFormStep} /> )} {/* 3. Job Info */} {module === 2 && ( <JobInfo formik={formik} formStep={formStep} setModule={handleSetModule} setFormStep={handleSetFormStep} /> )} {/* 4. Product Info */} {module === 3 && ( <ProductInfo formik={formik} formStep={formStep} setModule={handleSetModule} setFormStep={handleSetFormStep} isSubmitting={isSubmitting} /> )} </form> ); }
关键注意点
- enableReinitialize: 开启这个选项后,当Redux中的
formValues变化(比如页面刷新从localStorage读取),Formik会自动重新加载最新值。 - 状态同步时机: 通过
useEffect监听formik.values的变化,每次输入都会同步到Redux,确保状态实时一致。 - 性能优化: 如果担心频繁dispatch影响性能,可以用深比较(比如
lodash.isEqual)判断值是否真的变化后再dispatch,一般场景下Redux Toolkit的immer处理足够高效,无需额外优化。
内容的提问来源于stack exchange,提问作者Hols
相关产品推荐
相关产品推荐

