Formikのチュートリアルへようこそ。このチュートリアルでは、Reactでシンプルで複雑なフォームを作成するために必要なすべてを学ぶことができます。
すぐにでもローカルマシンで作業を始めたい場合は、60秒クイックスタートをご覧ください。
このチュートリアルでは、ReactとFormikを使用して複雑なニュースレター登録フォームを作成します。
作成する内容はこちらで確認できます:最終結果。コードが理解できない場合でも心配しないでください!このチュートリアルの目標は、Formikを理解するのに役立つことです。
Formikとその仕組みを完全に理解するには、HTML、CSS、モダンJavaScript、およびReact(およびReact Hooks)に関する知識が必要です。このチュートリアルでは、アロー関数、let、const、スプレッド構文、デストラクチャリング、計算されたプロパティ名、およびasync/awaitを使用しています。Babel REPLを使用して、ES6コードがどのようにコンパイルされるかを確認できます。
このチュートリアルを完了するには、2つの方法があります。ブラウザでコードを作成するか、コンピュータにローカル開発環境を設定します。
これは最も迅速な開始方法です!
まず、このスターターコードを新しいタブで開きます。新しいタブには、メールアドレス入力、送信ボタン、いくつかのReactコードが表示されます。このチュートリアルでは、Reactコードを編集します。
2番目の設定オプションをスキップして、概要セクションに進み、Formikの概要を確認してください。
これは完全にオプションであり、このチュートリアルには必要ありません!
この設定にはより多くの作業が必要ですが、選択したエディタを使用してチュートリアルを完了できます。手順は以下のとおりです。
npx create-react-app my-app
npm i formik
または
yarn add formik
注意
`src` フォルダー全体を削除しないでください。内部にある元のソースファイルのみを削除してください。次の手順では、このプロジェクトの例を使用してデフォルトのソースファイルを置き換えます。
cd my-appcd src# If you’re using a Mac or Linux:rm -f *# Or, if you’re on Windows:del *# Then, switch back to the project foldercd ..
`src/` フォルダーに `styles.css` という名前のファイルを追加し、このCSSコードを追加します。
`src/` フォルダーに `index.js` という名前のファイルを追加し、このJSコードを追加します。
次に、プロジェクトフォルダーで `npm start` を実行し、ブラウザで `http://localhost:3000` を開きます。メール入力と送信ボタンが表示されます。
エディタの構文ハイライトを設定するには、これらの手順に従うことをお勧めします。
行き詰まった場合は、FormikのGitHubディスカッションを確認してください。さらに、FormiumコミュニティDiscordサーバーは、迅速なヘルプを得るための優れた方法でもあります。回答を受け取れない場合、または行き詰まったままである場合は、問題を報告してください。お手伝いいたします。
Formikは、ReactとReact Nativeでフォームを作成するための、少数のReactコンポーネントとフックのグループです。最も厄介な3つの部分を支援します。
Formikは上記をすべて一箇所に配置することで、整理整頓を維持し、フォームのテスト、リファクタリング、および推論を簡単に行うことができます。
Formikを使用する最も冗長な方法から始めます。これは少し回りくどいように見えるかもしれませんが、Formikがどのように構築されているかを理解し、それがどのように機能するかの完全なメンタルモデルを持つことが重要です。
ブログのニュースレター登録フォームを追加したいとしましょう。まず、フォームには `email` という名前のフィールドが1つだけあります。Formikを使用すると、これはわずか数行のコードです。
import React from 'react';import { useFormik } from 'formik';const SignupForm = () => {// Pass the useFormik() hook initial form values and a submit function that will// be called when the form is submittedconst formik = useFormik({initialValues: {email: '',},onSubmit: values => {alert(JSON.stringify(values, null, 2));},});return (<form onSubmit={formik.handleSubmit}><label htmlFor="email">Email Address</label><inputid="email"name="email"type="email"onChange={formik.handleChange}value={formik.values.email}/><button type="submit">Submit</button></form>);};
フォームの `initialValues` と送信関数 (`onSubmit`) を `useFormik()` フックに渡します。フックは、`formik` と呼ぶ変数に、フォームの状態とヘルパーメソッドの詰め合わせを返します。今のところ、重要なヘルパーメソッドは次のとおりです。
上記のように、それぞれをそれぞれのpropsに渡します…それだけ!これで、Formikを搭載した機能するフォームを作成できます。フォームの値を自分で管理し、各入力ごとに独自のイベントハンドラーを作成する代わりに、`useFormik()` を使用できます。
これはかなり素晴らしいですが、入力は1つだけで、`useFormik()` を使用する利点は不明です。そこで、ユーザーの名前と姓を入力するためのさらに2つの入力(フォームでは `firstName` と `lastName` として保存)を追加しましょう。
import React from 'react';import { useFormik } from 'formik';const SignupForm = () => {// Note that we have to initialize ALL of fields with values. These// could come from props, but since we don’t want to prefill this form,// we just use an empty string. If we don’t do this, React will yell// at us.const formik = useFormik({initialValues: {firstName: '',lastName: '',email: '',},onSubmit: values => {alert(JSON.stringify(values, null, 2));},});return (<form onSubmit={formik.handleSubmit}><label htmlFor="firstName">First Name</label><inputid="firstName"name="firstName"type="text"onChange={formik.handleChange}value={formik.values.firstName}/><label htmlFor="lastName">Last Name</label><inputid="lastName"name="lastName"type="text"onChange={formik.handleChange}value={formik.values.lastName}/><label htmlFor="email">Email Address</label><inputid="email"name="email"type="email"onChange={formik.handleChange}value={formik.values.email}/><button type="submit">Submit</button></form>);};
新しいコードをよく見ると、いくつかのパターンと対称性が生まれていることに気付くでしょう。
プレーンなReactを使用してフォームを作成することに慣れている場合は、Formikの `handleChange` は次のように機能すると考えることができます。
const [values, setValues] = React.useState({});const handleChange = event => {setValues(prevValues => ({...prevValues,// we use the name to tell Formik which key of `values` to update[event.target.name]: event.target.value});}
連絡先フォームは機能しますが、機能は完全ではありません。ユーザーは送信できますが、どのフィールド(もしあれば)が必要なのかは通知されません。
ブラウザの組み込みHTML入力バリデーションを使用しても構わない場合は、各入力に `required` プロパティを追加し、最小/最大長(`maxlength` と `minlength`)、またはこれらの各入力の正規表現バリデーションのための `pattern` プロパティを指定できます。これらは、それらを使用できる場合は素晴らしいです。ただし、HTMLバリデーションには限界があります。まず、ブラウザでのみ機能します!そのため、React Nativeでは明らかに実行できません。第二に、ユーザーにカスタムエラーメッセージを表示することは困難または不可能です。第三に、非常にぎこちないものです。
前述のように、Formikはフォームの `values` だけでなく、そのバリデーションとエラーメッセージも追跡します。JSでバリデーションを追加するには、カスタムバリデーション関数を指定し、`useFormik()` フックに `validate` として渡します。エラーが存在する場合は、このカスタムバリデーション関数は、`values` / `initialValues` と一致する形状の `error` オブジェクトを生成する必要があります。繰り返しますが… _対称性_ …はい…
import React from 'react';import { useFormik } from 'formik';// A custom validation function. This must return an object// which keys are symmetrical to our values/initialValuesconst validate = values => {const errors = {};if (!values.firstName) {errors.firstName = 'Required';} else if (values.firstName.length > 15) {errors.firstName = 'Must be 15 characters or less';}if (!values.lastName) {errors.lastName = 'Required';} else if (values.lastName.length > 20) {errors.lastName = 'Must be 20 characters or less';}if (!values.email) {errors.email = 'Required';} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {errors.email = 'Invalid email address';}return errors;};const SignupForm = () => {// Pass the useFormik() hook initial form values, a validate function that will be called when// form values change or fields are blurred, and a submit function that will// be called when the form is submittedconst formik = useFormik({initialValues: {firstName: '',lastName: '',email: '',},validate,onSubmit: values => {alert(JSON.stringify(values, null, 2));},});return (<form onSubmit={formik.handleSubmit}><label htmlFor="firstName">First Name</label><inputid="firstName"name="firstName"type="text"onChange={formik.handleChange}value={formik.values.firstName}/>{formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}<label htmlFor="lastName">Last Name</label><inputid="lastName"name="lastName"type="text"onChange={formik.handleChange}value={formik.values.lastName}/>{formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}<label htmlFor="email">Email Address</label><inputid="email"name="email"type="email"onChange={formik.handleChange}value={formik.values.email}/>{formik.errors.email ? <div>{formik.errors.email}</div> : null}<button type="submit">Submit</button></form>);};
`formik.errors` はカスタムバリデーション関数によって設定されます。デフォルトでは、Formikはキーストローク(変更イベント)ごと、各入力のblurイベントごと、および送信前にバリデーションを実行します。`useFormik()` に渡した `onSubmit` 関数は、エラーがない場合(つまり、`validate` 関数が `{}` を返す場合)のみ実行されます。
フォームは機能しており、ユーザーは各エラーを確認できますが、ユーザーエクスペリエンスとしては最適ではありません。バリデーション関数はすべてのフォームのvalues
に対して各キーストロークで実行されるため、errors
オブジェクトには、任意の時点ですべてのバリデーションエラーが含まれます。コンポーネントでは、エラーが存在するかどうかをチェックし、すぐにユーザーに表示しています。ユーザーがまだアクセスしていないフィールドのエラーメッセージも表示されるため、これは不適切です。ほとんどの場合、ユーザーがそのフィールドへの入力を終えた後に、フィールドのエラーメッセージを表示するだけで十分です。
errors
やvalues
と同様に、Formikはどのフィールドがアクセスされたか追跡します。この情報は、values
/initialValues
の形状を反映するtouched
というオブジェクトに格納されます。touched
のキーはフィールド名、値はブール値true
/false
です。
touched
を活用するために、各入力のonBlur
プロパティにformik.handleBlur
を渡します。この関数は、name
属性を使用して更新するフィールドを特定するという点で、formik.handleChange
と同様に機能します。
import React from 'react';import { useFormik } from 'formik';const validate = values => {const errors = {};if (!values.firstName) {errors.firstName = 'Required';} else if (values.firstName.length > 15) {errors.firstName = 'Must be 15 characters or less';}if (!values.lastName) {errors.lastName = 'Required';} else if (values.lastName.length > 20) {errors.lastName = 'Must be 20 characters or less';}if (!values.email) {errors.email = 'Required';} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {errors.email = 'Invalid email address';}return errors;};const SignupForm = () => {const formik = useFormik({initialValues: {firstName: '',lastName: '',email: '',},validate,onSubmit: values => {alert(JSON.stringify(values, null, 2));},});return (<form onSubmit={formik.handleSubmit}><label htmlFor="firstName">First Name</label><inputid="firstName"name="firstName"type="text"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.firstName}/>{formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}<label htmlFor="lastName">Last Name</label><inputid="lastName"name="lastName"type="text"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.lastName}/>{formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}<label htmlFor="email">Email Address</label><inputid="email"name="email"type="email"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.email}/>{formik.errors.email ? <div>{formik.errors.email}</div> : null}<button type="submit">Submit</button></form>);};
もうすぐです!touched
を追跡できるようになったので、エラーメッセージのレンダリングロジックを変更して、特定のフィールドのエラーメッセージを、それが存在しかつユーザーがそのフィールドにアクセスした場合にのみ表示するようにできます。
import React from 'react';import { useFormik } from 'formik';const validate = values => {const errors = {};if (!values.firstName) {errors.firstName = 'Required';} else if (values.firstName.length > 15) {errors.firstName = 'Must be 15 characters or less';}if (!values.lastName) {errors.lastName = 'Required';} else if (values.lastName.length > 20) {errors.lastName = 'Must be 20 characters or less';}if (!values.email) {errors.email = 'Required';} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {errors.email = 'Invalid email address';}return errors;};const SignupForm = () => {const formik = useFormik({initialValues: {firstName: '',lastName: '',email: '',},validate,onSubmit: values => {alert(JSON.stringify(values, null, 2));},});return (<form onSubmit={formik.handleSubmit}><label htmlFor="firstName">First Name</label><inputid="firstName"name="firstName"type="text"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.firstName}/>{formik.touched.firstName && formik.errors.firstName ? (<div>{formik.errors.firstName}</div>) : null}<label htmlFor="lastName">Last Name</label><inputid="lastName"name="lastName"type="text"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.lastName}/>{formik.touched.lastName && formik.errors.lastName ? (<div>{formik.errors.lastName}</div>) : null}<label htmlFor="email">Email Address</label><inputid="email"name="email"type="email"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.email}/>{formik.touched.email && formik.errors.email ? (<div>{formik.errors.email}</div>) : null}<button type="submit">Submit</button></form>);};
上記のように、バリデーションはユーザー自身に任されています。独自のバリデーターを作成するか、サードパーティのヘルパーライブラリを使用できます。Formikの開発者/多くのユーザーは、Jason QuenseのライブラリYupをオブジェクトスキーマのバリデーションに使用しています。YupはJoiやReact PropTypesと同様のAPIを持っていますが、ブラウザでも動作し、ランタイムでも十分な速度です。このREPLで試すことができます。
Formikの開発者/ユーザーがYupを非常に気に入っているため、FormikにはYup用の特別な設定プロパティvalidationSchema
があります。これは、Yupのバリデーションエラーメッセージを、values
/initialValues
/touched
とキーが一致する(カスタムバリデーション関数と同じように)美しいオブジェクトに自動的に変換します。いずれにしても、NPM/yarnからYupを次のようにインストールできます…
npm install yup --save# or via yarnyarn add yup
Yupの動作を確認するために、カスタムバリデーション関数validate
を削除し、YupとvalidationSchema
を使用してバリデーションを書き直してみましょう。
import React from 'react';import { useFormik } from 'formik';import * as Yup from 'yup';const SignupForm = () => {const formik = useFormik({initialValues: {firstName: '',lastName: '',email: '',},validationSchema: Yup.object({firstName: Yup.string().max(15, 'Must be 15 characters or less').required('Required'),lastName: Yup.string().max(20, 'Must be 20 characters or less').required('Required'),email: Yup.string().email('Invalid email address').required('Required'),}),onSubmit: values => {alert(JSON.stringify(values, null, 2));},});return (<form onSubmit={formik.handleSubmit}><label htmlFor="firstName">First Name</label><inputid="firstName"name="firstName"type="text"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.firstName}/>{formik.touched.firstName && formik.errors.firstName ? (<div>{formik.errors.firstName}</div>) : null}<label htmlFor="lastName">Last Name</label><inputid="lastName"name="lastName"type="text"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.lastName}/>{formik.touched.lastName && formik.errors.lastName ? (<div>{formik.errors.lastName}</div>) : null}<label htmlFor="email">Email Address</label><inputid="email"name="email"type="email"onChange={formik.handleChange}onBlur={formik.handleBlur}value={formik.values.email}/>{formik.touched.email && formik.errors.email ? (<div>{formik.errors.email}</div>) : null}<button type="submit">Submit</button></form>);};
繰り返しますが、Yupは完全にオプションです。しかし、試してみることをお勧めします。上記のように、30行のコードではなく、わずか10行のコードでまったく同じバリデーション関数を表現できました。Formikの中核となる設計原則の1つは、整理整頓を支援することです。Yupは間違いなくこの点で大きく役立ちます。スキーマは非常に表現力豊かで直感的(値を反映するため)であり、再利用可能です。Yupを使用するかどうかとは関係なく、アプリケーション全体で一般的に使用されるバリデーションメソッドを共有することを強くお勧めします。これにより、一般的なフィールド(例:メールアドレス、住所、ユーザー名、電話番号など)の一貫したバリデーションが保証され、より良いユーザーエクスペリエンスにつながります。
getFieldProps()
上記のコードは、Formikが正確に何をしているかを非常に明確に示しています。onChange
-> handleChange
、onBlur
-> handleBlur
などです。しかし、時間を節約するために、useFormik()
はヘルパーメソッドformik.getFieldProps()
を返し、入力の接続を高速化します。フィールドレベルの情報が与えられると、特定のフィールドのonChange
、onBlur
、value
、checked
の正確なグループが返されます。それをinput
、select
、またはtextarea
に展開できます。
import React from 'react';import { useFormik } from 'formik';import * as Yup from 'yup';const SignupForm = () => {const formik = useFormik({initialValues: {firstName: '',lastName: '',email: '',},validationSchema: Yup.object({firstName: Yup.string().max(15, 'Must be 15 characters or less').required('Required'),lastName: Yup.string().max(20, 'Must be 20 characters or less').required('Required'),email: Yup.string().email('Invalid email address').required('Required'),}),onSubmit: values => {alert(JSON.stringify(values, null, 2));},});return (<form onSubmit={formik.handleSubmit}><label htmlFor="firstName">First Name</label><inputid="firstName"type="text"{...formik.getFieldProps('firstName')}/>{formik.touched.firstName && formik.errors.firstName ? (<div>{formik.errors.firstName}</div>) : null}<label htmlFor="lastName">Last Name</label><input id="lastName" type="text" {...formik.getFieldProps('lastName')} />{formik.touched.lastName && formik.errors.lastName ? (<div>{formik.errors.lastName}</div>) : null}<label htmlFor="email">Email Address</label><input id="email" type="email" {...formik.getFieldProps('email')} />{formik.touched.email && formik.errors.email ? (<div>{formik.errors.email}</div>) : null}<button type="submit">Submit</button></form>);};
上記のコードは、Formikが正確に何をしているかを非常に明確に示しています。onChange
-> handleChange
、onBlur
-> handleBlur
などです。しかし、各入力にこの「プロップゲッター」getFieldProps()
を手動で渡す必要があります。さらに時間を節約するために、FormikにはReactコンテキストベースのAPI/コンポーネントが付属しており、より簡単にコードを簡潔にすることができます:<Formik />
、<Form />
、<Field />
、<ErrorMessage />
。より具体的には、Reactコンテキストを暗黙的に使用して、親<Formik />
の状態/メソッドに接続します。
これらのコンポーネントはReactコンテキストを使用するため、フォームの状態とヘルパーをツリーに保持するReactコンテキストプロバイダーをレンダリングする必要があります。自分でこれを行うと、次のようになります。
import React from 'react';import { useFormik } from 'formik';// Create empty contextconst FormikContext = React.createContext({});// Place all of what’s returned by useFormik into contextexport const Formik = ({ children, ...props }) => {const formikStateAndHelpers = useFormik(props);return (<FormikContext.Provider value={formikStateAndHelpers}>{typeof children === 'function'? children(formikStateAndHelpers): children}</FormikContext.Provider>);};
幸いにも、<Formik>
コンポーネントでこれを行いました。これはまさにこれと同じように機能します。
これで、useFormik()
フックをFormikの<Formik>
コンポーネント/レンダープロップに置き換えます。コンポーネントなので、useFormik()
に渡されたオブジェクトをJSXに変換し、各キーをプロップにします。
import React from 'react';import { Formik } from 'formik';import * as Yup from 'yup';const SignupForm = () => {return (<FormikinitialValues={{ firstName: '', lastName: '', email: '' }}validationSchema={Yup.object({firstName: Yup.string().max(15, 'Must be 15 characters or less').required('Required'),lastName: Yup.string().max(20, 'Must be 20 characters or less').required('Required'),email: Yup.string().email('Invalid email address').required('Required'),})}onSubmit={(values, { setSubmitting }) => {setTimeout(() => {alert(JSON.stringify(values, null, 2));setSubmitting(false);}, 400);}}>{formik => (<form onSubmit={formik.handleSubmit}><label htmlFor="firstName">First Name</label><inputid="firstName"type="text"{...formik.getFieldProps('firstName')}/>{formik.touched.firstName && formik.errors.firstName ? (<div>{formik.errors.firstName}</div>) : null}<label htmlFor="lastName">Last Name</label><inputid="lastName"type="text"{...formik.getFieldProps('lastName')}/>{formik.touched.lastName && formik.errors.lastName ? (<div>{formik.errors.lastName}</div>) : null}<label htmlFor="email">Email Address</label><input id="email" type="email" {...formik.getFieldProps('email')} />{formik.touched.email && formik.errors.email ? (<div>{formik.errors.email}</div>) : null}<button type="submit">Submit</button></form>)}</Formik>);};
上記のように、useFormik()
フックを<Formik>
コンポーネントに置き換えました。<Formik>
コンポーネントは、子として関数を受け入れます(別名レンダープロップ)。その引数は、useFormik()
によって返されるオブジェクトとまったく同じです(実際、<Formik>
は内部的にuseFormik()
を呼び出します!)。したがって、フォームは以前と同じように機能しますが、新しいコンポーネントを使用して、より簡潔な方法で表現できるようになりました。
import React from 'react';import { Formik, Field, Form, ErrorMessage } from 'formik';import * as Yup from 'yup';const SignupForm = () => {return (<FormikinitialValues={{ firstName: '', lastName: '', email: '' }}validationSchema={Yup.object({firstName: Yup.string().max(15, 'Must be 15 characters or less').required('Required'),lastName: Yup.string().max(20, 'Must be 20 characters or less').required('Required'),email: Yup.string().email('Invalid email address').required('Required'),})}onSubmit={(values, { setSubmitting }) => {setTimeout(() => {alert(JSON.stringify(values, null, 2));setSubmitting(false);}, 400);}}><Form><label htmlFor="firstName">First Name</label><Field name="firstName" type="text" /><ErrorMessage name="firstName" /><label htmlFor="lastName">Last Name</label><Field name="lastName" type="text" /><ErrorMessage name="lastName" /><label htmlFor="email">Email Address</label><Field name="email" type="email" /><ErrorMessage name="email" /><button type="submit">Submit</button></Form></Formik>);};
<Field>
コンポーネントは、デフォルトで<input>
コンポーネントをレンダリングします。これは、name
プロップが与えられると、それぞれのonChange
、onBlur
、value
プロップを暗黙的に取得して要素に渡すと同時に、渡されたプロップも渡します。しかし、すべてが入力ではないため、<Field>
は、自由にレンダリングできるようにいくつかのプロップも受け入れます。いくつかの例…
// <input className="form-input" placeHolder="Jane" /><Field name="firstName" className="form-input" placeholder="Jane" />// <textarea className="form-textarea"/></textarea><Field name="message" as="textarea" className="form-textarea" />// <select className="my-select"/><Field name="colors" as="select" className="my-select"><option value="red">Red</option><option value="green">Green</option><option value="blue">Blue</option></Field>
Reactはコンポジションがすべてであり、プロップドリリングを多く削減しましたが、各入力にlabel
、<Field>
、<ErrorMessage>
を繰り返しています。抽象化でより良いことができます!Formikを使用すると、アプリケーション全体で共有できる再利用可能な入力プリミティブコンポーネントを作成できます。<Field>
レンダープロップコンポーネントには姉妹がいて、その名前はuseField
で、同じことを行いますが、Reactフックを使用します!ご覧ください…
import React from 'react';import ReactDOM from 'react-dom';import { Formik, Form, useField } from 'formik';import * as Yup from 'yup';const MyTextInput = ({ label, ...props }) => {// useField() returns [formik.getFieldProps(), formik.getFieldMeta()]// which we can spread on <input>. We can use field meta to show an error// message if the field is invalid and it has been touched (i.e. visited)const [field, meta] = useField(props);return (<><label htmlFor={props.id || props.name}>{label}</label><input className="text-input" {...field} {...props} />{meta.touched && meta.error ? (<div className="error">{meta.error}</div>) : null}</>);};const MyCheckbox = ({ children, ...props }) => {// React treats radios and checkbox inputs differently from other input types: select and textarea.// Formik does this too! When you specify `type` to useField(), it will// return the correct bag of props for you -- a `checked` prop will be included// in `field` alongside `name`, `value`, `onChange`, and `onBlur`const [field, meta] = useField({ ...props, type: 'checkbox' });return (<div><label className="checkbox-input"><input type="checkbox" {...field} {...props} />{children}</label>{meta.touched && meta.error ? (<div className="error">{meta.error}</div>) : null}</div>);};const MySelect = ({ label, ...props }) => {const [field, meta] = useField(props);return (<div><label htmlFor={props.id || props.name}>{label}</label><select {...field} {...props} />{meta.touched && meta.error ? (<div className="error">{meta.error}</div>) : null}</div>);};// And now we can use theseconst SignupForm = () => {return (<><h1>Subscribe!</h1><FormikinitialValues={{firstName: '',lastName: '',email: '',acceptedTerms: false, // added for our checkboxjobType: '', // added for our select}}validationSchema={Yup.object({firstName: Yup.string().max(15, 'Must be 15 characters or less').required('Required'),lastName: Yup.string().max(20, 'Must be 20 characters or less').required('Required'),email: Yup.string().email('Invalid email address').required('Required'),acceptedTerms: Yup.boolean().required('Required').oneOf([true], 'You must accept the terms and conditions.'),jobType: Yup.string().oneOf(['designer', 'development', 'product', 'other'],'Invalid Job Type').required('Required'),})}onSubmit={(values, { setSubmitting }) => {setTimeout(() => {alert(JSON.stringify(values, null, 2));setSubmitting(false);}, 400);}}><Form><MyTextInputlabel="First Name"name="firstName"type="text"placeholder="Jane"/><MyTextInputlabel="Last Name"name="lastName"type="text"placeholder="Doe"/><MyTextInputlabel="Email Address"name="email"type="email"placeholder="jane@formik.com"/><MySelect label="Job Type" name="jobType"><option value="">Select a job type</option><option value="designer">Designer</option><option value="development">Developer</option><option value="product">Product Manager</option><option value="other">Other</option></MySelect><MyCheckbox name="acceptedTerms">I accept the terms and conditions</MyCheckbox><button type="submit">Submit</button></Form></Formik></>);};
上記のように、useField()
を使用すると、あらゆる種類のReactコンポーネントを入力として<Field>
+ <ErrorMessage>
のようにFormikに接続できます。これを使用して、ニーズに合った再利用可能な入力グループを作成できます。
おめでとうございます!Formikを使用してサインアップフォームを作成しました。
素晴らしい仕事です!Formikの仕組みをある程度理解できたことを願っています。
最終的な結果はこちらをご覧ください:最終結果。
時間がある場合、または新しいFormikスキルを練習したい場合は、難易度順にサインアップフォームを改善するためのアイデアをいくつかご紹介します。
formik.isSubmitting
)。formik.handleReset
または<button type="reset">
を使用して、リセットボタンを追加します。<SignupForm>
に渡されたプロップに基づいてinitialValues
を事前に設定します。このチュートリアルでは、フォームの状態、フィールド、バリデーション、フック、レンダープロップ、Reactコンテキストなど、Formikの概念について説明しました。これらのトピックの詳細については、その他のドキュメントを参照してください。チュートリアルでコンポーネントとフックを定義する方法の詳細については、APIリファレンスを参照してください。