lil.dev
Published on

๐ŸŽ‰ ์ปฌ๋Ÿฌ๋ฆฌ์ŠคํŠธ ํ”„๋กœ์ ํŠธ #19 VerticalForm - Form ์ถ”์ƒํ™”

๊ธ€์“ด์ด

    ๐Ÿ“Œ

    Welcome

    โœจ ์ปฌ๋Ÿฌ๋ฆฌ์ŠคํŠธ ์‚ฌ์ดํŠธ(์•„์ง ์—†์Œ

    Form ์ถ”์ƒํ™”

    ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€์™€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋Š” ๋น„์Šทํ•œ ์šฉ๋„์™€ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง„ form์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
    ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋‘ ํŽ˜์ด์ง€์˜ form์„ ๊ฐ๊ฐ ๋งŒ๋“ค๊ธฐ๋ณด๋‹ค, ์ถ”์ƒํ™”๋œ form์„ ๋งŒ๋“ค์–ด ๊ฐ๊ฐ์˜ ํŽ˜์ด์ง€์—
    ๋งž๊ฒŒ ๋ณ€ํ˜•ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ผ๊ด€์„ฑ์ด ๋†’์€ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ๋œ๋‹ค.

    1. ๊ธฐ์กด์˜ Login ํŽ˜์ด์ง€์— ์žˆ๋Š” form

    ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์—์„œ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํŽ˜์ด์ง€์˜ ์ œ๋ชฉ๊ณผ ๋ฒ„ํŠผ์•ˆ์— ๋“ค์–ด๊ฐ€๋Š” ํ…์ŠคํŠธ๋“ค์€ ํŽ˜์ด์ง€๋งˆ๋‹ค ๋ฐ”๋€Œ๋ฏ€๋กœ ํƒ€์ž…์„ ์ •ํ•ด์ฃผ๊ณ  props๋กœ ๋นผ๋‚ธ๋‹ค. ๋ฒ„ํŠผ ๊ฐ™์€ ๊ฒฝ์šฐ ๋ฒ„ํŠผ ์ž์ฒด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฉ์–ด๋ฆฌ๋กœ ์ด๋™ํ•˜๋Š”๊ฒŒ ๋” ์ข‹์œผ๋ฏ€๋กœ, ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด์šฉํ•ด ์ปดํฌ๋„ŒํŠธ ์ „์ฒด๋ฅผ after๋ผ๋Š” ํƒ€์ž…์— ๋„ฃ์–ด ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.

    ๊ทธ๋ฆฌ๊ณ  input๋“ค์€ children์œผ๋กœ ๋งŒ๋“ค์–ด VerticalForm์•ˆ์— fragment๋ฅผ ๋„ฃ๊ณ  (VerticalForm์•ˆ์—๋Š” ํ•˜๋‚˜์˜ <>๋งŒ ๋„ฃ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ) ๊ทธ ์•ˆ์— ์˜ฎ๊ฒจ์ค€๋‹ค.

    import { useForm } from 'react-hook-form'
    import { Link } from 'react-router-dom'
    import Button from '~/components/Button'
    import VerticalForm from '~/components/VerticalForm'
    
    function Register() {
      const {
        register,
        handleSubmit,
        formState: { errors },
      } = useForm({
        defaultValues: {
          email: '',
          password: '',
        },
      })
    
      return (
        <VerticalForm
          title="ํšŒ์›๊ฐ€์ž…"
          submitLabel="๊ฐ€์ž…ํ•˜๊ธฐ"
          onSubmit={handleSubmit((data) => {
            alert(JSON.stringify(data))
          })}
          after={
            <Button as={Link} to="/login" className="text-center">
              ๋กœ๊ทธ์ธ์œผ๋กœ ์ด๋™
            </Button>
          }
        >
          <>
            <label className="flex flex-col gap-2">
              <span className="text-xl">์ด๋ฉ”์ผ</span>
              <input
                type="email"
                className="input input-bordered"
                {...register('email', {
                  required: '์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”!',
                })}
              />
            </label>
            {errors.email && <li role="alert">{errors.email.message}</li>}
    
            <label className="flex flex-col gap-2">
              <span className="text-xl">๋น„๋ฐ€๋ฒˆํ˜ธ</span>
              <input
                type="password"
                className="input input-bordered"
                {...register('password', {
                  required: '๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”!',
                })}
              />
            </label>
            {errors.password && <li role="alert">{errors.password.message}</li>}
          </>
        </VerticalForm>
      )
    }
    
    // react jsx์— ๋‚ด์žฅ๋˜์–ด ์žˆ๋Š”... ์ฆ‰ ์›๋ž˜ html element์—๋„ ์žˆ๋Š” ํƒ€์ž…๋“ค์€... ๋ฌธ์ž์—ด๋กœ ์“ธ ์ˆ˜ ์žˆ๋‹ค! "a" "button" "input"
    
    export default Register
    

    ์œ„์˜ ์ฝ”๋“œ ์•ˆ์— ์žˆ๋Š” title,submitLabel๊ณผ after์•ˆ์— ๋“ค์–ด๊ฐ€๋Š” ๋ฌธ์ž์—ด์€ Form์•ˆ์— ์จ์ฃผ๋Š”๋Œ€๋กœ ํŽ˜์ด์ง€๋งˆ๋‹ค ๋ณด์ด๋Š” ๋‚ด์šฉ์ด ๋‹ฌ๋ผ์ง„๋‹ค.