Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use with useFormik hook? #34

Open
saifalfalah opened this issue Jul 25, 2020 · 2 comments
Open

How to use with useFormik hook? #34

saifalfalah opened this issue Jul 25, 2020 · 2 comments

Comments

@saifalfalah
Copy link

When trying to use Formik using the useFormik, I understandably get the following warning:

Warning: Formik context is undefined, please verify you are rendering <Form>, <Field>, <FastField>, <FieldArray>, or your custom context-using component as a child of a <Formik> component. Component name: PersistImpl

And data is not persisting. What should I do?

@victor-abz
Copy link

victor-abz commented May 13, 2021

This is working for me...

import { useEffect, useRef, useMemo } from 'react';
import { useFormikContext } from 'formik';
import debounce from 'lodash.debounce';
import isEqual from 'react-fast-compare';

// Copied from https://usehooks.com/usePrevious/
// License is Unlicensed, https://github.com/gragland/usehooks/blob/master/LICENSE
function usePrevious(value) {
	// The ref object is a generic container whose current property is mutable ...
	// ... and can hold any value, similar to an instance property on a class
	var ref = useRef();
	// Store current value in ref
	useEffect(
		function () {
			ref.current = value;
		},
		[value]
	); // Only re-run if value changes
	// Return previous value (happens before update in useEffect above)
	return ref.current;
}

const FormikPersist = ({
	name,
	debounceDelay = 300,
	isSessionStorage = false
}) => {
	// Define formik props
	let formikProps = useFormikContext();

	const saveForm = useMemo(
		() =>
			debounce((data) => {
				// Save formik state to session or local storage
				isSessionStorage
					? sessionStorage.setItem(name, JSON.stringify(data))
					: localStorage.setItem(name, JSON.stringify(data));
			}, debounceDelay),
		[debounceDelay, isSessionStorage, name]
	);

	// Destructure formik props
	// prettier-ignore
	let {setFormikState, dirty, values, errors, touched, isValid, isSubmitting } = formikProps;

	// On component mounted
	useEffect(() => {
		const restoreFormikState = async () => {
			// Get formik state
			const savedState = isSessionStorage
				? await JSON.parse(sessionStorage.getItem(name))
				: await JSON.parse(localStorage.getItem(name));

			// Restore formik state
			if (savedState) {
				await setFormikState(savedState);
			}
		};

		restoreFormikState();
	}, []);

	// On values change
	var previousValues = usePrevious(formikProps.values);

	useEffect(() => {
		if (previousValues && !isEqual(previousValues, values)) {
			saveForm(formikProps);
		}
	}, [dirty, values, errors, touched, isValid, isSubmitting]);

	// Render null
	return null;
};

export default FormikPersist;

@suhaotian
Copy link

Look this! 👀: https://github.com/suhaotian/use-formik-persist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants