Search code examples
reactjsreact-reduxredux-toolkitformik

What is the best way to save Formik values in Redux Toolkit so that I can persist them with redux-persist?


I have a multi step form made in React with formik and I am also using Redux Toolkit with redux-persist. I am able to save the form steps in the Redux state and the user remains in the current step even if they close/open the window again. But how can I also store the formik values he has entered in the Redux state so that the values persist as well?

This is the code of my form:

export default function UserDetailsForm() {
  const formik = useFormik({
    initialValues: FormInitialValues,
    validationSchema: FORM_MODULES[module]?.schema[formStep],
    onSubmit: (values, actions) => {
      sendFormRequest(values, actions);
    },
  });

  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>
  )
}

Thanks in advance.


Solution

  • First create a state slice for your draft values then you can watch values changes returned from useFormik hooks and trigger an action to save them.

    useEffect(() => {
        dispatch(saveDraftValues(formik.values)) 
    }, [formik.values])
    

    You can add the step as dependency to save the draft values only when a step is finished to avoid triggering multiple action on form changes

    useEffect(() => {
        dispatch(saveDraftValues(formik.values)) 
    }, [step])
    

    Then you can get the value from the store, for instance formDraft slice and if it's not null set your initial values with the draft values

    const dispatch = useDispatch()
    const formDraft = useSelector((state: RootState) => state.formDraft.value);
    const formik = useFormik({
     initialValues: formDraft || FormInitialValues,
     validationSchema: FORM_MODULES[module]?.schema[formStep],
     onSubmit: (values, actions) => {
       sendFormRequest(values, actions);
     },
    });
    
    useEffect(() => {
     dispatch(saveDraftValues(formik.values)) 
    }, [step])