formik の FieldArray を扱うときに、key に index を使用したくない

2020-04-08

linter 的に良くないので、回避方法を模索しました。

ちなみに、公式サイトは諦めているみたいです、楽だしね。

import { Field, FieldArray, FieldArrayConfig, Form, Formik, FormikConfig, } from "formik"; import React, { FC, useCallback, useMemo, useState } from "react"; import uniqid from "uniqid"; type Hoge = { fuga: string; piyo: number; }; type AppValues = { hoges: Hoge[]; }; type HogesProperty = { handleClickRemoveButton: () => void; key: string; }; const App: FC = () => { const initialValues = useMemo<FormikConfig<AppValues>["initialValues"]>( () => ({ hoges: [], }), [] ); const handleSubmit = useCallback<FormikConfig<AppValues>["onSubmit"]>( (values) => { console.log(values); }, [] ); const [hogesProperties, setHogesProperties] = useState<HogesProperty[]>([]); const renderHoges = useCallback<NonNullable<FieldArrayConfig["children"]>>( ({ push, remove }) => { const handleClickAddButton = () => { const key = uniqid(); push({ fuga: "", piyo: 0, }); setHogesProperties((prevHogesProperties) => ([] as typeof hogesProperties).concat(prevHogesProperties, [ { key, handleClickRemoveButton: () => { setHogesProperties((prevHogesProperties) => { const index = prevHogesProperties.findIndex( ({ key: prevKey }) => key === prevKey ); // かなり強引 remove(index); return prevHogesProperties.filter( (_, prevIndex) => index !== prevIndex ); }); }, }, ]) ); }; const hogesFields = hogesProperties.map( ({ handleClickRemoveButton, key }, index) => ( <div key={key}> <Field name={`hoges.${index}.fuga`} /> <Field name={`hoges.${index}.piyo`} type="number" /> {key} <button onClick={handleClickRemoveButton} type="button"> remove </button> </div> ) ); return ( <div> <button onClick={handleClickAddButton} type="button"> add </button> {hogesFields} </div> ); }, [hogesProperties, setHogesProperties] ); return ( <Formik initialValues={initialValues} onSubmit={handleSubmit}> <Form> <FieldArray name="hoges">{renderHoges}</FieldArray> <button type="submit">submit</button> </Form> </Formik> ); }; export default App;

remove を呼ぶタイミングがかなり強引なんですが、ここしか思いつかず…。

container を量産したくないケースでは使えそうですが、パフォーマンスはあまり良くなさそうです。

© 2018 kk-web