React

지난시간 복습

export default function HofPage() {
  const router = useRouter();

  const onClickMove = (boardId: any) => (event: any) => {
    router.push(`/${boardId}`);
  };

  function onClickMove(boardId) {
    return function asdfasf(event) {
      console.log(boardId)
      console.log(event)
    }
  }

로컬 스코프에 있는지 확인 후 없으면 클로저 스코프에 가서 스코프 체인 해서 가져온다

클로저 스코프가 2개인 경우 (펑션 안에 펑션 안에 펑션)
asdfasf 가 끝나야 onclickmove가 끝나고 그게끝나야 aaa가 끝남

  function aaa() {
    function onClickMove(boardId) {
      return function asdfasf(event) {
        console.log(boardId);
        console.log(event);
      };
    }
  }

useApolloClient

useQuery는 유저정보를 사용하는 페이지가 많다면, 모든 페이지에서 useQuery를 해와야 한다는 번거로움이 있다. useQuery를 효율적으로 사용하는 방법은?

여러가지 쿼리 방식

  • useQuery: 컴포넌트가 열리면 바로 실행되며, data라는 변수에 fetch해온 데이터를 담아줌
  • useLazyQuery: useQuery를 원하는 시점에 실행 후 fetch해온 데이터를 data변수에 담아줌
  • useApolloClient: 원하는 시점에 실행 후 fetch해온 데이터를 원하는 변수에 담을 수 있음(axios 같은 느낌)

useLazyQuery는 useQuery와 useApolloClient의 중간쯤..으로 보자

useQuery 방식
const{data} = useQuery()
useLazyQuery 방식
const[aaa, {data}] = useLazyQuery()
aaa()

하면 실행은 되는데 결과 데이터가 useQuery()처럼 data에 들어옴
그래서 원할 때 요청을 할 수 있긴 하지만 
원하는 변수에 담아서 사용할 수 없기 때문에 렌더링 용도임

렌더링 용도가 아니라 2차적인 저장을 하려면 useApolloClient 사용해야 함!

폼 라이브러리(react-hook-form)

폼 라이브러리를 사용하면 (모든 스테이트 직접만들기, 온체인지 함수 일일히 바인딩해주기) 등의 노가다성 코딩을 하지 않아도 돼서 굉장히 간편

폼 라이브러리에는 react-form, redux-form, react-hook-form, formik 등이 있다

react-hook-form

우리가 이전에 사용하면 onchange를 만들어서 setState를 해주고 바인딩 하는 방뻡은 state가 변화할때마다 렌더링이 되기 때문에 불필요한 렌더링이 지속적으로 일어나 굉장히 비효율적이고, 변화한 state를 다시 받아서 넣어주기 때문에 굉장히 느리다

하지만 react-hook-form은 input의 값을 실시간으로 state에 반영하는것이 아니라, 등록함수가 실행될 때 한번에 처리하기 때문에 불필요한 렌더링이 제거되고 한번에 바꿔서 렌더링하기 대문에 빠르고 효율적! 인
비제어 컴포넌트 이다

  • 제어 컴포넌트(controlled) : 사용자의 입력을 기반으로 state를 실시간으로 관리(setState 사용)
  • 비제어 컴포넌트(uncontrolled) : 바닐라 자바스크립트처럼 sumit함수를 실행할 때 ref로 input값을 끌고옴

한치의 오차도 용납할 수 없는 중요한 데이터를 저장하고 있다면 제어 컴포넌트를 이용하는게 좋지만 그런게 아니면 비제어 컴포넌트를 이용해서 성능을 높여주는게 더 좋다!

react-hook-form 사용

const ReactHookForm = ()=>{
	// react-hook-form 에서 useForm을 제공합니다.
	const {register , handleSubmit} = useForm()

	// 등록하기 함수 -> handleSubmit이 조종해주는 함수 입니다.
	const onClickSubmit = (data)=>{
		console.log(data)
	}

	return(
		<form onSubmit={handleSubmit(onClickSubmit)}>
			<input type="text" {...register("state이름")}/>
			<button type="reset"> 등록하기 </button>
		</form>
	)
}
export default ReactHookForm

💡 register, handleSubmit, form
register : state를 등록하는데 필요한 모든 기능이 들어있음
handleSubmit : resister에 적힌 state를 등록해주는 함수
form : 실제 html에 있는 input들을 묶어주는 태그

리랜더링 안되고 스테이트 받아오는거 확인 가능!

검증 라이브러리(yup)

숫자인지, 문자인지, 8자리인지, 특수문자가 들어가는지 등의 까다로운 검증과정을 대신해주는 라이브러리

import * as yup from 'yup'
import {useForm} from 'react-hook-form'
import {yupResolver} from '@hookform/resolvers/yup'
import styled from '@emotion/styled'

const myButton = styled.button`
background-color : ${(props)=>props.isValid ? "yellow" : ""}
`

// yup 에러메세지 생성해주기
const schema = yup.object().shape({
	myWriter : yup.string()
								.email('이메일 형식이 적합하지 않습니다.')
								.required('필수 입력값입니다.')
	myPassword : yup.string()
									.min(4,'비밀번호는 최소 4자리 이상입니다.')
									.max(15,'비밀번호는 최대15자리 입니다.')
									.required('필수 입력값 입니다.') 
})

const ReactHookForm = ()=>{
	//formState에서 에러메세지들을 받아오게 됩니다.
	const {register , handleSubmit, formState} = useForm({
		// schema는 위에서 만들어 둔 schema입니다.
		resolver : yupResolver(schema)
	})

	// 등록하기 함수 -> handleSubmit이 조종해주는 함수 입니다.
	const onClickSubmit = (data)=>{
		console.log(data)
	}

	return(
		<form onSubmit={handleSubmit(onClickSubmit)}>
			이메일 : <input type="text" {...register("myEmail")}/>
				<div> {formState.error.myEmail?.message}</div>
			비밀번호 : <input type="text" {...register("myPassword")}/>
				<div> {formState.error.myPassword?.message}</div>
			<MyButton type="reset" isValid={isValid}> 등록하기 </button>
		</form>
	)
}
export default ReactHookForm

에러가 있을수도 있고 없을수도 있기때문에 옵셔널 체이닝을 사용해서 조건부 렌더링을 걸어주고,
최종적으로 에러가 있는지 있는지 없는지 확인후 formState의 isValid를 사용해서 버튼 활성화 시키기

공통 컴포넌트

commons 폴더에 button, input 어쩌구 저쩌구 다 만들어서 공통 컴포넌트로 만들어 분리해서 필요할 때 마다 꺼내서 편리하게 하자 !

import styled from "@emotion/styled";

const Button = styled.button`
  background-color: ${(props) => (props.isValid ? "pink" : "default")};
`;
export default function Button01(props: any) {
  return <Button isValid={props.isValid}>{props.title}</Button>;
}
export default function Input01(props: any) {
  return <input type={props.type} {...props.register} />;
  // return <input type={props.type} {...props.register} onChange={props.onChange}/>;
}

++
주말동안,, 글로벌 스테이지부터 복습하기,,

Bearer 부분 다시 보기

주말에 if문으로 걸어줬던것들 오늘 배운 yup으로 변경해서 코드 길이 줄여주기,,조금씩 조금씩...해야지 왜냐면 너무 많으니까 오백개는 되는 것 같으니까

라이브러리 리스트!
중요한 라이브러리 목록 정리해두기
어떤 라이브러리 써야할지 알고 있어야 해,, (다운로드 수 가튼거 보고서 정하기)

profile
어제보다 오늘 발전하는 프론트엔드 개발자

0개의 댓글