Formikを使用しているときに、入力に合わせて自動送信させたかったので、調べて実装してみました。
方針
FormikのuseFormikContextを使用する!
FormikのForm内の子コンポーネント等で呼び出すと、Formikの変数や関数を取得することができます。values
, submitForm
, isValid
など色々取得できます!
コード例
onSubmitを実行させる場合
useFormikContextからsubmitForm関数も取得できるので、それを実行させます。
import React, {useEffect} from 'react';
import { useFormikContext, Formik, Form, Field } from 'formik';
type FormValues = {
name: string
email: string
}
const AutoSubmitToken = () => {
const { values, submitForm } = useFormikContext<FormValues>(); // ココ。TypeScriptでない場合は<>内は不要。
useEffect(() => {
if (/^[a-zA-Z0-9_+-]+(.[a-zA-Z0-9_+-]+)*@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/.test(values.email)) {
submitForm(); // ココ
}
}, [values.email]); // values.emailに変更があったときにuseEffectが動く
return null;
};
const ExampleForm = () => (
<div>
<Formik
initialValues={{ name: '', email: '' }}
onSubmit={(values: FormValues) => {alert(`name: ${values.name}, email: ${values.email}`)}}
>
<Form>
<Field name="name" />
<Field name="email" type="email" />
<AutoSubmitToken />
</Form>
</Formik>
</div>
);
任意の関数を実行させる場合
実行関数をpropとして渡せば、任意の関数の実行もできます。
import React, {useEffect} from 'react';
import { useFormikContext, Formik, Form, Field } from 'formik';
type FormValues = {
name: string
email: string
}
const AutoSubmitToken: React.FC<{submitHandler: (arg: string)=>void}> = ({submitHandler}) => {
const { values } = useFormikContext<FormValues>(); // ココ。TypeScriptでない場合は<>内は不要。
useEffect(() => {
if (/^[a-zA-Z0-9_+-]+(.[a-zA-Z0-9_+-]+)*@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/.test(values.email)) {
submitHandler(values.email);
}
}, [values.email]); // values.emailに変更があったときにuseEffectが動く
return null;
};
const ExampleForm: React.FC = () => {
const submitEmail = (email: string): void => {
alert(`valid email: ${email}`)
}
return (
<div>
<Formik
initialValues={{ name: '', email: '' }}
onSubmit={(values: FormValues) => {alert(`name: ${values.name}, email: ${values.email}`)}}
>
<Form>
<Field name="name" />
<Field name="email" type="email" />
<AutoSubmitToken submitHandler={submitEmail} />
</Form>
</Formik>
</div>
);
}