diff options
author | Masaya Tojo <masaya@tojo.tokyo> | 2024-08-05 23:26:43 +0900 |
---|---|---|
committer | Masaya Tojo <masaya@tojo.tokyo> | 2024-08-05 23:26:43 +0900 |
commit | 7fa73728582e2dfb26ff89786c27dd9da97bebc2 (patch) | |
tree | f0bf9963b8e88bde91cf5dc3d0049bf063d5b886 | |
parent | ff4f0419c31c93399c38a689c2a2c9b0114d7b49 (diff) |
zod でバリデーションを試す
-rw-r--r-- | src/SignUp.css | 10 | ||||
-rw-r--r-- | src/SignUp.tsx | 64 |
2 files changed, 74 insertions, 0 deletions
diff --git a/src/SignUp.css b/src/SignUp.css index e69de29..602ed0a 100644 --- a/src/SignUp.css +++ b/src/SignUp.css @@ -0,0 +1,10 @@ +.SignUpForm { + display: flex; + flex-direction: column; + gap: 15px; +} + +.error { + margin: 0; + color: red; +} diff --git a/src/SignUp.tsx b/src/SignUp.tsx index d812b35..2a7f448 100644 --- a/src/SignUp.tsx +++ b/src/SignUp.tsx @@ -1,9 +1,73 @@ import './SignUp.css' +import { useState } from "react"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod" + +const schema = z.object({ + name: z.string(), + email: z.string().email("それメアドじゃないよ"), + birthday: z.coerce.date().max(new Date(), { message: "まだ生まれてないじゃん" }), + language: z.string(), +}) + +type Answer = { + name: string, + email: string, + birthday: Date, + language: string, +} export const SignUp = () => { + const { register, handleSubmit, reset, formState: { errors } } = useForm<Answer>({ + resolver: zodResolver(schema) + }); + const [answer, setAnswer] = useState<Answer | null>(null); + + const yourAnswer = answer ? ( + <> + <h2>あなたの情報です</h2> + <dl> + <dt>おぬしの名前は…</dt> + <dd>{answer.name}</dd> + <dt>おぬしのメアドは…</dt> + <dd>{answer.email}</dd> + <dt>あなたの誕生日</dt> + <dd>{answer.birthday.getFullYear()}年{answer.birthday.getMonth()}月{answer.birthday.getDay()}日</dd> + <dt>おぬしの好きなプログラミング言語は…</dt> + <dd>{answer.language}</dd> + </dl> + </> + ) : (<></>) + return ( <> <h1>会員登録</h1> + <form className="SignUpForm" onSubmit={handleSubmit((data) => setAnswer(data))}> + <label>お名前:</label> + <input {...register("name")} placeholder="おなまえ" /> + {errors.name?.message} + <label>めるあど</label> + <input {...register("email", { required: true })} placeholder="めるあど" /> + {errors.email?.message && <p className="error">{errors.email?.message}</p>} + <label>生まれた日</label> + <input {...register("birthday", { required: true })} placeholder="yyyy/mm/dd" /> + {errors.birthday?.message && <p className="error">{errors.birthday?.message}</p>} + <label>好きなプログラミング言語</label> + <select {...register("language", { required: true })}> + <option value="">Select...</option> + <option value="Gulie">Guile</option> + <option value="Gauche">Gauche</option> + <option value="Racket">Racket</option> + <option value="Larceny">Larceny</option> + <option value="Chicken">Chicken</option> + </select> + {errors.language?.message && <p className="error">{errors.language?.message}</p>} + <input type="submit" /> + <button type="button" onClick={() => reset()}>消す</button> + </form> + + {yourAnswer} </> ); } |