今回実装するもの
validationはzodで、UIはmaterial UIを使っていきます。
ライブラリインストール
- zod(型検証ライブラリ)
- Material UI(UIフレームワーク)
npm install zod
npm install @mui/material @emotion/react @emotion/styled
Material UIはreactのUIフレームワークです。
公式ドキュメントに色々UIコンポーネントの例が掲載されていて、コピペするだけできれいなUIが実装できてとても便利です。
zodは型検証ライブラリです。
zodに関して詳しく知りたい方はこの記事が勉強になると思います。
実装
UIの実装
まずはUIを実装してしまいましょう。
material UIコンポーネントを使って雑に実装します。
import { Box, Button, TextField } from '@mui/material';
function App() {
return (
<>
<Box textAlign={'center'} margin={'20px 0'}>
<TextField
label="名前"
variant="outlined"
required
/>
<Box>
<Button>提出</Button>
</Box>
</Box>
</>
);
}
これで以下のようになると思います。
以下がそれぞれのオプションの説明です。
オプション | 概要 |
---|---|
label | 表示するラベルの設定 |
variant | 表示デザインの設定(詳しくは公式ドキュメント参照) |
required | 必須項目かの設定(これをtrueにすると * がつきます) |
user変数の定義
それではここで入力した値を変数に束縛します。
import { Box, Button, TextField } from '@mui/material';
import { ChangeEvent, useState } from 'react';
import {z} from 'zod'
const User = z.object({
name: z.string().min(1)
})
type User = z.infer<typeof User>
function App() {
const inputHandler = (event: ChangeEvent<HTMLInputElement>) => {
setUser({
name: event.target.value
})
}
const [user, setUser] = useState<User>()
return (
<>
<Box textAlign={'center'} margin={'20px 0'}>
<TextField
autoComplete='off'
label="名前"
variant="outlined"
required
onChange={inputHandler}
/>
<Box>
<Button onClick={submitHandler}>提出</Button>
</Box>
</Box>
</>
);
}
export default App;
ここで、zodがでてきました。
今はnameしかないですが、実際使う時はemailやpasswordなどの他の要素もあるかもなので、User型はobject型にしてみています。
そして、nameは1文字以上のstring型に設定しています。
あとは onChangeでTextFieldに値が入力されたら発火するhandlerを作ってその中でsetUserを用いてe.target.value
をuserに束縛しました。
バリデーションの実装
最後にバリデーションを実現します。
先ほど、User型に変数を束縛したのであとは先ほど入れた値がUser型に一致しているか検証してあげればいいだけです。
import { Box, Button, TextField } from '@mui/material';
import { ChangeEvent, useState } from 'react';
import {z} from 'zod'
const User = z.object({
name: z.string().min(1)
})
type User = z.infer<typeof User>
function App() {
const inputHandler = (event: ChangeEvent<HTMLInputElement>) => {
setUser({
name: event.target.value
})
}
const submitHandler = () => {
const parseResult = User.safeParse(user)
if (!parseResult.success) {
setError(true)
}else{
setError(false)
}
}
const [user, setUser] = useState<User>()
const [error, setError] = useState<boolean>()
return (
<>
<Box textAlign={'center'} margin={'20px 0'}>
<TextField
autoComplete='off'
label="名前"
variant="outlined"
required
name="name"
onChange={inputHandler}
helperText={error ? '1文字以上入力してください' : ''}
error={error}
/>
<Box>
<Button onClick={submitHandler}>提出</Button>
</Box>
</Box>
</>
);
}
export default App;
buttonをクリックするとsubmitHandlerが発火して、zodの型検証をしてくれます。
zodで定義した型に対してsafeParse
してあげると、パース結果がsuccess
にてbooleanで渡されます。
(User.parseとすることもできますが、これはパースに失敗するとエラーを投げるのでtry, catchなどで例外処理が必要になります)
こうすることによって、パースに失敗したらerrorフラグをtrueにします。
そして、TextFieldの中でerrorがtrueのときにhelperTextを表示して、errorオプションをtrueに設定します。
errorオプションをtreuにすることで枠が赤くなってくれます。Material UI様様です。
helperTextは追加テキストを表示してくれます。Material UI様様です。
これで、validationを実装することができました!
終わりに
今回はこんな感じでバリデーションを実装してみました。
こんな書き方のほうがかっこいいとか、こんな方法もあるとか、ここ間違えてるよとかご意見ある方いらっしゃったらコメントください。