Skip to content

Instantly share code, notes, and snippets.

@mwmcode
Last active December 18, 2019 09:42
Show Gist options
  • Save mwmcode/d3aac9afbcd079ad4857b9e922359612 to your computer and use it in GitHub Desktop.
Save mwmcode/d3aac9afbcd079ad4857b9e922359612 to your computer and use it in GitHub Desktop.
formik persist state (sessionStorage | localStorage) using hooks
import { useRef, useEffect } from 'react';
import useExtractFormikState from './useExtractFormikState';
type PersistProps = {
name: string;
type?: 'local' | 'session';
}
export default function FormikPersist(props: PersistProps): null {
const { name, type = 'session' } = props;
const valsRef = useRef<Record<string, any>>({});
const [state, setState] = useExtractFormikState();
valsRef.current = state;
const storageType = `${type}Storage`;
useEffect(() => {
const maybeState = window[storageType].getItem(name);
if (maybeState) {
setState(JSON.parse(maybeState));
}
return (): void => {
window[storageType].setItem(name, valsRef.current);
};
}, [type, name]);
return null;
}
// use the same way here https://github.com/jaredpalmer/formik-persist
import React from 'react';
import { Formik, Field, Form } from 'formik';
import Persist from './Persist';
export const Signup = () =>
<div>
<h1>My Cool Persisted Form</h1>
<Formik
onSubmit={values => console.log(values)}
initialValues={{ firstName: '', lastName: '', email: '' }}
render={props =>
<Form className="whatever">
<Field name="firstName" placeholder="First Name" />
<Field name="lastName" placeholder="Last Name" />
<Field name="email" type="email" placeholder="Email Address" />
<button type="submit">Submit</button>
<Persist name="signup-form" />
</Form>}
/>
</div>;
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useFormikContext, FormikValues, FormikState } from 'formik';
const StateKeys = [
'errors',
// 'isSubmitting',
// 'isValidating',
'status',
'submitCount',
'touched',
'values',
];
export default function useExtractFormikState(): [
Partial<FormikState<any>>,
(f: Partial<FormikState<any>>) => void,
] {
const formikVals: FormikValues = useFormikContext<FormikValues>();
const state = StateKeys.reduce((state: FormikValues, key: string) => {
state[key] = formikVals[key];
return state;
}, {});
function setState(newState: Partial<FormikState<any>>): void {
if (JSON.stringify(formikVals.values) !== JSON.stringify(newState.values)) {
formikVals.setFormikState((prev: FormikState<any>) => ({
...prev,
...newState,
}));
}
}
return [state, setState];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment