Reputation: 6041
There is a basic Formik form:
<Formik
initialValues={{ email: '', color: 'red', firstName: '' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
render={props => (
<form onSubmit={props.handleSubmit}>
<Field type="email" name="email" placeholder="Email" />
<div>other inputs ... </div>
<button type="submit">Submit</button>
</form>
)}
/>
When any input in it changes (not submits, but changes) - I need to update another component that is outside of <Formik />
. The "outside" component should receive all form data.
Is there some way to do it without adding separate change handler for each individual input of a form? Or the solution is to try to insert "outside" component inside <Formik />
?
Upvotes: 6
Views: 6576
Reputation: 335
You should not call setState
during the render cycle of a component, as has been suggested:
<Formik
render={props => (
setformValues(props.values) // store values in state 'formValues'
// ...
)}
/>
Rather, you should call setState
as a side-effect. A more verbose, yet better solution would be:
// handle when form values change
const FormikOnChange = ({ onChange }) => {
const { values } = useFormikContext()
useEffect(
() => {
onChange(values)
},
[values]
)
return null
}
const App () => {
const [formValues, setformValues] = useState(initialValues)
// ...do stuff with form values...
return (
<Formik
render={props => (
<FormikOnChange onChange={setformValues} /> // store values in state 'formValues'
// ...
)}
/>
)
}
Upvotes: 1
Reputation: 85
export const LoginForm: React.FC<Values> = () => {
const initialValues = { user: "", password: "" };
const [formValues, setformValues] = React.useState(initialValues);
return (
<div>{formValues.user}</div>
<Formik
initialValues={initialValues}
validationSchema={ValidationSchema}
onSubmit={(values, { setSubmitting, resetForm }) => {
setTimeout(() => {
//alert(JSON.stringify(values, null, 2));
resetForm();
setSubmitting(false);
setformValues(values);
}, 500);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
}) => {
return (
<>
<TextField
label="Usuario"
name="user"
value={values.user}
onChange={handleChange}
onBlur={handleBlur}
fullWidth
color={touched.user && errors.user ? "primary" : "secondary"}
/>
<Error touched={touched.user} message={errors.user} />
</>
<div className="pane-form__submit">
<Button
className={classes.customHoverFocus}
variant="contained"
type="submit"
disabled={isSubmitting}
label="CONTINUAR"
>Continuar</Button>
</div>
</Form>
)
}}
</Formik>
</>
);
};
Upvotes: -1
Reputation: 2258
Formik
provides values
object which you can make use of to get values outside.
const App = () => {
const initialValues = { email: '', color: 'red', firstName: '' }
const [formValues, setformValues] = useState(initialValues);
const getFormData = values => {
// access values here
};
return (
<div>
<h1>Formik take values outside</h1>
<Formik
initialValues={initialValues}
...
>
{props => {
setformValues(props.values); // store values in state 'formValues'
getFormData(props.values); // or use any function to get values like this
return (
<form onSubmit={props.handleSubmit}>
...
Working demo in codesandbox here
Upvotes: 10