You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 17:47:05