<FieldArray />
は、一般的な配列/リスト操作を支援するコンポーネントです。関連する配列を保持するキーへのパスを `name` プロパティに渡します。<FieldArray />
は、レンダリングプロップスを介して配列ヘルパーメソッドへのアクセスを提供します。これらのメソッドを呼び出すと、バリデーションがトリガーされ、touched
も管理されます。
import React from 'react';import { Formik, Form, Field, FieldArray } from 'formik';// Here is an example of a form with an editable list.// Next to each input are buttons for insert and remove.// If the list is empty, there is a button to add an item.export const FriendList = () => (<div><h1>Friend List</h1><FormikinitialValues={{ friends: ['jared', 'ian', 'brent'] }}onSubmit={values =>setTimeout(() => {alert(JSON.stringify(values, null, 2));}, 500)}render={({ values }) => (<Form><FieldArrayname="friends"render={arrayHelpers => (<div>{values.friends && values.friends.length > 0 ? (values.friends.map((friend, index) => (<div key={index}><Field name={`friends.${index}`} /><buttontype="button"onClick={() => arrayHelpers.remove(index)} // remove a friend from the list>-</button><buttontype="button"onClick={() => arrayHelpers.insert(index, '')} // insert an empty string at a position>+</button></div>))) : (<button type="button" onClick={() => arrayHelpers.push('')}>{/* show this when user has removed all friends from the list */}Add a friend</button>)}<div><button type="submit">Submit</button></div></div>)}/></Form>)}/></div>);
name: string
values
内の関連キーの名前またはパス。
validateOnChange?: boolean
デフォルトはtrue
です。配列操作の後、フォームのバリデーションを実行するかどうかを決定します。
<Field />
または<input />
要素のname属性にobject[index].property
またはobject.index.property
という規則に従うことで、オブジェクトの配列を反復処理することもできます。
<Form><FieldArrayname="friends"render={arrayHelpers => (<div>{values.friends.map((friend, index) => (<div key={index}>{/** both these conventions do the same */}<Field name={`friends[${index}].name`} /><Field name={`friends.${index}.age`} /><button type="button" onClick={() => arrayHelpers.remove(index)}>-</button></div>))}<buttontype="button"onClick={() => arrayHelpers.push({ name: '', age: '' })}>+</button></div>)}/></Form>
<FieldArray>
では、バリデーションが複雑になる可能性があります。
validationSchema
を使用し、フォームに配列のバリデーション要件(最小長など)とネストされた配列フィールドの要件がある場合、エラーの表示が複雑になる可能性があります。Formik/Yupは、内側から外側へとバリデーションエラーを表示します。例えば、
const schema = Yup.object().shape({friends: Yup.array().of(Yup.object().shape({name: Yup.string().min(4, 'too short').required('Required'), // these constraints take precedencesalary: Yup.string().min(3, 'cmon').required('Required'), // these constraints take precedence})).required('Must have friends') // these constraints are shown if and only if inner constraints are satisfied.min(3, 'Minimum of 3 friends'),});
Yupとカスタムバリデーション関数は常にエラーメッセージを文字列として出力する必要があるため、表示する際にネストされたエラーが配列か文字列かを判別する必要があります。
そのため、「友達が必要です」と「最低3人の友達が必要です」(例の配列バリデーション制約)を表示するには…
悪い例
// within a `FieldArray`'s renderconst FriendArrayErrors = errors =>errors.friends ? <div>{errors.friends}</div> : null; // app will crash
良い例
// within a `FieldArray`'s renderconst FriendArrayErrors = errors =>typeof errors.friends === 'string' ? <div>{errors.friends}</div> : null;
ネストされたフィールドエラーについては、確認するまでオブジェクトのどの部分も定義されていないと想定する必要があります。そのため、次のようなカスタム<ErrorMessage />
コンポーネントを作成することをお勧めします。
import { Field, getIn } from 'formik';const ErrorMessage = ({ name }) => (<Fieldname={name}render={({ form }) => {const error = getIn(form.errors, name);const touch = getIn(form.touched, name);return touch && error ? error : null;}}/>);// Usage<ErrorMessage name="friends[0].name" />; // => null, 'too short', or 'required'
注記:Formik v0.12/1.0では、error
とtouch
などの関連メタデータを提供する新しいmeta
プロップがField
とFieldArray
に追加される可能性があり、FormikやlodashのgetInを使用したり、パスが自分で定義されているかどうかを確認したりする必要がなくなります。
以下のメソッドは、レンダリングプロップスを介して使用できます。
push: (obj: any) => void
: 配列の最後に値を追加しますswap: (indexA: number, indexB: number) => void
: 配列内の2つの値を入れ替えますmove: (from: number, to: number) => void
: 配列内の要素を別のインデックスに移動しますinsert: (index: number, value: any) => void
: 指定されたインデックスに要素を配列に挿入しますunshift: (value: any) => number
: 配列の先頭に要素を追加し、その長さを返しますremove<T>(index: number): T | undefined
: 配列のインデックスにある要素を削除し、それを返しますpop<T>(): T | undefined
: 配列の末尾から値を削除して返しますreplace: (index: number, value: any) => void
: 指定されたインデックスに値を配列に置き換えます<FieldArray />
で項目をレンダリングするには3つの方法があります。
<FieldArray name="..." component>
<FieldArray name="..." render>
<FieldArray name="..." children>
render: (arrayHelpers: ArrayHelpers) => React.ReactNode
import React from 'react';import { Formik, Form, Field, FieldArray } from 'formik'export const FriendList = () => (<div><h1>Friend List</h1><FormikinitialValues={{ friends: ['jared', 'ian', 'brent'] }}onSubmit={...}render={formikProps => (<FieldArrayname="friends"render={({ move, swap, push, insert, unshift, pop }) => (<Form>{/*... use these however you want */}</Form>)}/>/></div>);
component: React.ReactNode
import React from 'react';import { Formik, Form, Field, FieldArray } from 'formik'export const FriendList = () => (<div><h1>Friend List</h1><FormikinitialValues={{ friends: ['jared', 'ian', 'brent'] }}onSubmit={...}render={formikProps => (<FieldArrayname="friends"component={MyDynamicForm}/>)}/></div>);// In addition to the array helpers, Formik state and helpers// (values, touched, setXXX, etc) are provided through a `form`// propexport const MyDynamicForm = ({move, swap, push, insert, unshift, pop, form}) => (<Form>{/** whatever you need to do */}</Form>);
children: func
import React from 'react';import { Formik, Form, Field, FieldArray } from 'formik'export const FriendList = () => (<div><h1>Friend List</h1><FormikinitialValues={{ friends: ['jared', 'ian', 'brent'] }}onSubmit={...}render={formikProps => (<FieldArray name="friends">{({ move, swap, push, insert, unshift, pop, form }) => {return (<Form>{/*... use these however you want */}</Form>);}}</FieldArray>)}/></div>);
最新のFormikニュース、記事、リソースをメールで受信します。