react-hook-form

김종민·2022년 9월 15일
0

Nuber-Client

목록 보기
4/21


react-hook-form
햇갈리는 error부분만 잘 봐둔다.
useMutation은 빼고 react-hook-form부분만 다룬다.
select부분과
formState:{errors}를 잘 봐둔다.!!!!

1. src/pages/login.tsx

import { gql, useMutation } from '@apollo/client'
import React from 'react'
import { useForm } from 'react-hook-form'
import { Link } from 'react-router-dom'
import { authTokenVar, isLoggedInVar } from '../apollo'
import Button from '../components/button'
import { FormError } from '../components/form-error'
import { LoginMutation, LoginMutationVariables } from '../graphql/__generated__'
import { LOCALSTORAGE_TOKEN } from '../constant'

interface ILoginForm {
  email: string
  password: string
}

const LOGIN_MUTATION = gql`
  mutation login($loginInput: LoginInput!) {
    login(input: $loginInput) {
      ok
      token
      error
    }
  }
`

export const Login = () => {
  const {
    register,
    getValues,
    formState: { errors, isValid },
    handleSubmit,
  } = useForm<ILoginForm>({
    mode: 'onChange',
  })
///useForm으로 만들고 mode는 onChange,
///register, getValues, handleSubmit, formState:{errors, isValid}를 넣는다.

  const onCompleted = (data: LoginMutation) => {
    const {
      login: { ok, token },
    } = data
    if (ok && token) {
      console.log(token)
      localStorage.setItem(LOCALSTORAGE_TOKEN, token)
      authTokenVar(token)
      isLoggedInVar(true)
    }
  }

  const [loginMutation, { data: loginMutationResult, loading }] = useMutation<
    LoginMutation,
    LoginMutationVariables
  >(LOGIN_MUTATION, { onCompleted })

  const onSubmit = () => {
  ///email과 password 값을 form으로부터 getValues()한다.
  ///그리고 loginMutation의 variables로 보내준다.
  
    if (!loading) {
      const { email, password } = getValues()
      loginMutation({
        variables: {
          loginInput: {
            email,
            password,
          },
        },
      })
    }
  }

  return (
    <div className="h-screen flex items-center justify-center flex-col">
      <div className="w-full max-w-screen-sm flex flex-col px-5 items-center">
        <h3 className="w-full font-medium text-left text-3xl mb-5">
          Welcome Back
        </h3>
        <form
          onSubmit={handleSubmit(onSubmit)}
          className="grid gap-3 mt-3 mb-5 w-full"
        >
        ///react-hook-form 형태를 잘 봐둔다.
        ///formState:{error, isValid}부분이
        ///헷갈리니 잘 봐둔다..
          <input
            {...register('email', {
              required: 'Email is required',
              maxLength: { value: 30, message: 'max char is 30' },
            })}
            required
            maxLength={30}
            type="email"
            placeholder="Email"
            className="input"
          />
          {errors.email?.message && (
            <FormError errorMessage={errors.email.message} />
          )}
          <input
            {...register('password', { required: 'Password is required' })}
            name="password"
            type="password"
            placeholder="Password"
            className="input"
          />
          {errors.password?.message && (
            <FormError errorMessage={errors.password?.message} />
          )}
          ///Button component를 import함.
          ///component는 나중에 따로 다룰 예정!
          <Button loading={loading} actionText="Login" />
          {loginMutationResult?.login.error && (
            <FormError errorMessage={loginMutationResult?.login.error} />
          )}
        </form>
        <p className="text-center mt-5 text-base">
          계정이 없으신가요?
          <Link
            to="/signup"
            className="ml-2 font-semibold text-green-600 hover:underline"
          >
            회원가입
          </Link>
        </p>
      </div>
    </div>
  )
}

2. src/pages/create-account.tsx


***react-hook-form부분만 집중적으로 다뤄본다.

import { gql, useMutation } from '@apollo/client'
import React from 'react'
import { useForm } from 'react-hook-form'
import { Link } from 'react-router-dom'
import { useNavigate } from 'react-router-dom'
import Button from '../components/button'
import { FormError } from '../components/form-error'
import {
  CreateAccoountMutation,
  CreateAccoountMutationVariables,
  UserRole,
} from '../graphql/__generated__'

export const CREATE_ACCOUNT = gql`
  mutation createAccoount($createAccountInput: CreateAccountInput!) {
    createAccount(input: $createAccountInput) {
      ok
      error
    }
  }
`

interface ICreateAccountForm {
  email: string
  password: string
  role: UserRole
}

export const CreateAccount = () => {

  ///위의 login이랑 같음...
  const {
    register,
    getValues,
    formState: { errors, isValid },
    handleSubmit,
  } = useForm<ICreateAccountForm>({
    mode: 'onChange',
    defaultValues: { role: UserRole.Client },
  })

  const navigate = useNavigate()
  const onCompleted = (data: CreateAccoountMutation) => {
    const {
      createAccount: { ok },
    } = data
    if (ok) {
      alert('Account Created. Log in now.')
    }
  }
  const [createAccountMutation, { loading, data: createAccountMutaionResult }] =
    useMutation<CreateAccoountMutation, CreateAccoountMutationVariables>(
      CREATE_ACCOUNT,
      { onCompleted }
    )
  const onSubmit = () => {
  ///getValues해서 값을 variables:{createAccountInput에 보내줌..
  ///createAccountMutation을 실행
  
    if (!loading) {
      const { email, password, role } = getValues()
      createAccountMutation({
        variables: {
          createAccountInput: { email, password, role },
        },
      })
    }
  }

  return (
    <div className="h-screen flex flex-col items-center justify-center ">
      <div className="w-full max-w-screen-sm flex flex-col px-5 items-center">
        <h4 className="w-full font-medium text-lleft text-3xl mb-5">
          Let's get started
        </h4>
        <form
          onSubmit={handleSubmit(onSubmit)}
          className="grid gap-3 mt-5 mb-5 w-full"
        >
          <input
          ///react-hook-form형태!!!
          ///error 다루는 거만 집중해서 보자
            {...register('email', { required: 'Email is required' })}
            className="input"
            placeholder="email"
            type="email"
            required
          />
          {errors.email?.message && (
            <FormError errorMessage={errors.email?.message} />
          )}
          <input
            {...register('password', { required: 'Password is Required' })}
            className="input"
            placeholder="password"
            type="password"
            required
          />
          {errors.password?.message && (
            <FormError errorMessage={errors.password?.message} />
          )}
          
          ///select다루는 부분 집중해서 봐둘것!!!!
          <select {...register('role', { required: true })} className="input">
            {Object.keys(UserRole).map((role, index) => (
              <option key={index}>{role}</option>
            ))}
          </select>
          <Button loading={loading} actionText="Create Account" />
        </form>
        <div className="text-lg">
          Already have an account?{''}
          <Link to="/" className="text-green-400 hover:underline">
            Log in now
          </Link>
        </div>
      </div>
    </div>
  )
}

export default CreateAccount

!!!NOTICE select다루는 부분 집중해서 봐둔다
!!! formState:{error}다루는부분이랑.

profile
코딩하는초딩쌤

0개의 댓글