I use a formik form with forward refs like so
import React from "react";
import FormikWithRef from "./FormikWithRef";
const Form = ({
formRef,
children,
initialValues,
validationSchema,
onSubmit
}) => {
return (
<FormikWithRef
validateOnChange={true}
validateOnBlur={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
ref={formRef}
>
{(props) => <form onSubmit={props.handleSubmit}>{children}</form>}
</FormikWithRef>
);
};
export default Form;
import React, { forwardRef, useImperativeHandle } from "react";
import { Formik } from "formik";
function FormikWithRef(props, ref) {
let _formikProps = {};
useImperativeHandle(ref, () => _formikProps);
return (
<Formik {...props}>
{(formikProps) => {
_formikProps = formikProps;
if (typeof props.children === "function") {
return props.children(formikProps);
}
return props.children;
}}
</Formik>
);
}
export default forwardRef(FormikWithRef);
I have some tabs, that update an easy-peasy
store state type
, when I select the 2nd tab, I was wanting to update the input value (that initially comes from the store state of value
) with a Formik form, but updating state initialValues
specific to that component that gets passed as initialValues
prop to the Formik
component.
import React, { useState, useEffect, useRef } from "react";
import styled from "styled-components";
import { useStoreState } from "easy-peasy";
import Form from "./Form";
import MoneyBox from "./MoneyBox";
const Container = styled.div`
width: 100%;
background-color: #dfdfdf;
`;
const FieldWrapper = styled.div`
padding: 20px 12px;
`;
const TabsForm = () => {
const [initialValues, setInitialValues] = useState();
const type = useStoreState((state) => state.type);
const value = useStoreState((state) => state.value);
const formRef = useRef(null);
const onFormSubmit = async (values) => {
console.log({ values });
};
useEffect(() => {
if (value && type) {
let filterVal = { ...value };
/* here is where I update the input value to be 3000,
the initial values get updated and in the `Form.js` file,
the console log from here also reflects this update,
however, the input field does not update? */
if (type === "Two") filterVal.input = 30000;
setInitialValues(filterVal);
}
}, [value, type]);
useEffect(() => {
// check initialValues has updated
console.log({ initialValues });
}, [initialValues]);
return (
<Container>
{initialValues && type ? (
<Form
initialValues={initialValues}
onSubmit={onFormSubmit}
formRef={formRef}
>
<FieldWrapper>
<MoneyBox name="input" currencySymbol={"£"} />
</FieldWrapper>
</Form>
) : null}
</Container>
);
};
export default TabsForm;
When clicking the 2nd tab;
initialValues
state in TabsForms.js
updates so that value.input
= 30000
;initialValues
prop in both Form.js
and FormikWithRef.js
also reflect that value.input
= 3000
useField
hook from forimk
in the MoneyBox.js
component, the field
object does not have a value
of 30000
, instead it's whatever the field value was before, why is this?I have created a CodeSandbox to see all the components used, and console logs to see that the Formik does receive the updated value, but doesn't seem to apply it.
I've been stuck on this for a few days and can't seem to find a solution, any help would be greatly appreciated.
If you want the value of the input to change when you change initialValues
, you need to pass to the Formik
component the prop enableReinitialize
as true
.
So, what you need to change in your code is in TabsForm.js
pass to your Form
component the prop enableReinitialize
<Form
enableReinitialize
initialValues={initialValues}
onSubmit={onFormSubmit}
formRef={formRef}
>
<FieldWrapper>
<MoneyBox name="input" currencySymbol={"£"} />
</FieldWrapper>
</Form>
And in your Form.js
pass that prop to the Formik
component
const Form = ({
formRef,
children,
initialValues,
validationSchema,
onSubmit,
enableReinitialize
}) => {
return (
<FormikWithRef
enableReinitialize={enableReinitialize}
validateOnChange={true}
validateOnBlur={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
ref={formRef}
>
{(props) => <form onSubmit={props.handleSubmit}>{children}</form>}
</FormikWithRef>
);
};
I'm not quite sure how you business logic should work, but here is a working example with the changes above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With