LoginSignup
2
2

More than 5 years have passed since last update.

React Hooksでformもuseして型安全なフォーム生活

Posted at

はい。

とくちょう

簡単な例です。

import * as React from 'react';
import {FC} from 'react';

import {useForm, createFormScope} from 'mayoiga';
import {Input, NumberInput} from 'mayoiga/lib/forms';

const required = (target: string) => (target.length === 0 ? 'required' : undefined);

const between = (min: number, max: number) => (target: number) => {
  if (target < min) {
    return `more than ${min}`;
  }
  if (target > max) {
    return `less than ${max}`;
  }
};

const choice = function<T>(...candidates: Array<T>) {
  return (target: T) => (candidates.includes(target) ? undefined : 'You should choose from the candidates.');
};

const INITIAL_FORM_STATE = {
  name: '',
  age: 13,
  seed: 'fish',
};

const {context, scope} = createFormScope<typeof INITIAL_FORM_STATE>();

const DemoForm = scope(props => {
  const {Form, Field} = useForm(context);
  return (
    <Form onSubmit={value => console.log(value)}>
      <Field name="name" component={Input} validations={[required]} />
      <Field name="age" component={NumberInput} validations={[between(5, 20)]} />
      <Field name="seed" component={Input} validations={[choice('fish', 'squid', 'octopus')]} />

      <button disabled={!props.touched || Object.values(props.errors).some(e => !!e.length)}>submit</button>
    </Form>
  );
});

export default function DemoApp() {
  return <DemoForm initialState={INITIAL_FORM_STATE} onSubmit={value => alert(`submit ${JSON.stringify(value)}`)} />;
}

一番重要なのは

const {context, scope} = createFormScope<typeof INITIAL_FORM_STATE>();

const DemoForm = scope(props => {
  const {Form, Field} = useForm(context);
  return (
    <Form onSubmit={value => console.log(value)}>
      <Field name="name" component={Input} validations={[required]} />
      <Field name="age" component={NumberInput} validations={[between(5, 20)]} />
      <Field name="seed" component={Input} validations={[choice('fish', 'squid', 'octopus')]} />

      <button disabled={!props.touched || Object.values(props.errors).some(e => !!e.length)}>submit</button>
    </Form>
  );
});

export default function DemoApp() {
  return <DemoForm initialState={INITIAL_FORM_STATE} onSubmit={value => alert(`submit ${JSON.stringify(value)}`)} />;
}

のくだりですね。
useForm できます。え、すごーい! キャッシュも結構きかせてるからパフォーマンスも悪くないっぽいよ!(たぶん)

そしてこのライブラリは型を頑張ってるので <Field /> に渡すnameが createFormScope で渡した型引数のkeyに存在しない値である場合はTypeScriptがエラーを出してくれます。これでageと間違えてsageても問題ありませんね。
さらにcomponent=で渡しているコンポーネントの valueonChangeState[Name](たとえばageであればINITIAL_FORM_STATE['age']の型と互換であるかどうか。つまりこの場合はnumberである必要がある)もチェックしてくれるんだって!

ちなみに<Form />レベルのonSubmitはoptionalです。

特徴を簡単にまとめると

  • 型がかなり効く
  • useFormできるので最新版を使っているという気持ちになれる。ボイラープレートコードが少ない
  • ちょっとしたグルーを書けばantdやbootstrapやmaterialやらwhateverと簡単に連携できる

です。

こちら にもうちょっと詳しい説明があります。


最後にこの動画が面白い、役に立つと思った方は高評価とチャンネル登録、リポジトリにスターをお願いします。またね!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2