FE 25일차

jae·2022년 6월 10일
0
post-thumbnail

오늘의 다짐
할일을 미루지말자...
주말에 해야할 게 너무 많아...


오늘의 목표

  1. useQuery를 axios처럼 사용 할 수 있대 UseApolloclient

2.폼을 자동으로 만들어준다고? React-Hook-form

3.Validation 라이브러리도 있대 yup

4.재사용을 위한 공통컴포넌트 만들자 Common-Component

오늘 수강 이후로는 프롭스도 줄고 함수도 줄어버리게 될것
버튼이나 인풋도 공통 컴포넌트로 분리 할 것
그래서 쌓여가는 리팩토링...


어제 배운 것을 포트폴리오에 적용 하려면?

이렇게 클로저를 사용하여 함수 안에 함수 안에 함수... 이렇게 몇개씩 들어갈수 있다
클로저가 한번당 함수를 한번씩 올라갈수 있는데
이경우 맨 안의 함수가 완료가 되어야 그 위의 함수도 종료가 되기에
종료되지않으면 메모리 낭비가 될 수 있다.

{[
        {
          id: "111",
          title: "안녕하",
          writer: "철수",
          contents: "반갑습니다.",
        },
        { id: "222", title: "안녕요", writer: "영희", contents: "암튼 반가워" },
        { id: "333", title: "반갑습니다", writer: "훈이", contents: "그래요" },
      ].map((el) => (
        <div key={el.id} onClick={onClickMove(el.id)}>
          {el.title}
          {el.writer}

이렇게 map으로 그려진 리스트에서 글 을 클릭하면 그 페이지로 이동시키고 싶을떄

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

클로저를 이용하면 이렇게 하이오더펑션으로
이벤트 함수를 생성하면 쉽게 동작 시킬수 있다.

1. useQuery를 axios처럼 사용 할 수 있대 UseApolloclient

useQuery의 경우 유저 정보를 사용하는 페이지가 많다면 모든 페이지에서 useQuery를 해와야해서 번거로움..

쿼리의 방식에는 3가지가 있는데

  • useQuery : 컴포넌트가 열리면 바로 실행되며, data라는 변수에 fetch해온 데이터를 담아줍니다.
  • useLazyQuery : useQuery를 원하는 시점에 실행후 fetch해온 데이터를 data변수에 담아줍니다.
  • useApolloClient : 원하는 시점에 실행 후 fetch해온 데이터를 원하는 변수에 담을 수 있습니다. 따라서 axios 같은 느낌으로 사용이 가능합니다.

useApolloClient 에서 우릐의 목표는 로그인이 완료된 후 유저의 정보를
Success페이지에서 fetch 하는 것이 아닌 토큰과 함께 global state에 저장하는 것이 목표

토큰을 App.tsx안의 context에 저장을 하고 있기 때문에 같이 넣어주고 싶은 유저의 정보 또한 토큰과 함께 Contextdksdp userInfo라는 이름으로 저장

// src/components/commons/apollo/index.tsx

// Apollo Setting 빼주기
import { useRecoilState } from "recoil";
import { accessTokenState, userInfoState } from "../../../commons/store";

export default function ApolloSetting(props) {
	const [accessToken,setAccessToken] =useRecoilState(accessTokenState)
	const [userInfo,setUserInfo] = useRecoilState(userInfoState)

	useEffect(()=>{
		if(localStorage.getItem("accessToken")){
		setAccessToken(localStorage.getItem("accessToken")||"")
	}
},[])

	const uploadLink = createUploadLink({
			uri : "백엔드 주소",
			headers : { Authorization : ₩Bearer ${받아온 토큰} }
		})

	return (
		<ApolloProvider client={client}>
			{props.children}
		</ApolloProvider>
	)
}

recoil에 넣어줄 userInfo를 만들어준 후 userInfo를 import
이렇게 recoil에 토큰과 함께 유저의 정보가 담기게 됨

이제 로그인api를 요청할 떄 setUserInfo를 이용해 실제 유저의 정보를 state안에 넣어주면됨

하지만 useQuery는 요청한 mutation의 데이터를 fetch해오고 해당 데이터를 {data}에 담아 렌더링하고 있기 때문에 로그인을 요청하는 mutation 안에서 같이 사용할 수 없습니다.

따라서 useApolloClient를 사용해 내가 원하는 위치에서 사용 후 변수에 결과를 담아 사용해야 합니다.


2.폼을 자동으로 만들어준다고? React-Hook-form

컴포넌트는 2가지 종류로 나뉨

    1. 제어 컴포넌트 (cotrolled)
      기존의 다뤘던 컴포넌트
      사용자의 입력을 기반으로 state를 실시간으로 관리(setState 사용)
      직접 스테이트도 만들고 함수도 만들어서 바인딩
      스테이트가 변화할때마다 렌더링되어 불필요한 렌더링이 발생해 비효율적
      스테이트를 받아서 다시 넣어주고 렌더링하기에 느림
    1. 비제어 컴포넌트(uncontrolled)
      바닐라 자바스크립트 처럼 sumit함수를 실행할 때 ref 로 input값을 끌고옴

      react-form, redux-form, react-hook-form, formik 등이 있음
      그 중 react-hook-form을 사용 (https://react-hook-form.com/)
      input의 값을 실시간으로 state에 반영하는 것이 아닌 등록함수가 실행될떄 한번에 처리하기떄문에 불필요한 렌더링이 제거되고 한번에 바꿔 렌더링하기 때문에 빠르고 효율적

      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 : state를 등록하는데 필요한 모든 기능

- handleSubmit : resister에 적힌 state를 등록해주는 함수

- form : 실제 html에 있는 input들을 묶어주는 태그
	input에 적힌 내용을 전송해주는 기능
    
button 태그의 type에 reset을 주게 되면 클릭시에 폼 안에 있는 인풋값을 초기화
submit을 주시게 되면 form태그에 바인딩된 submit 함수를 실행시키게 됩니다.

버튼 타입의 기본은 submit입니다. 따라서 폼안에서 사용하게 되면, 따로 명시 하지 않아도 submit의 기능을 하게 됩니다.

작성자: 제목: 내용: 등록하기 ```

이렇게 될경우 type에 submit을 설정하면
form에 있는 onSubmit={}에 있는 함수가 실행됨
만약 버튼에 추가적으로 함수를 등록 한다면
type으로 인하여 두가지 함수가 실행되기때문에
원하지 않은 결과가 나올수 있으니 타입을 잘 설정할 것

이렇게 리액트 폼을 이용하여 register로 스테이트들을 만들어주고
hadlesubmit과 onClickSubmit으로 데이터를 보내줌

베리어블즈도 ...data로만 하면 되는 코드가 아주 짧아지는 라이브러리

3.Validation 라이브러리도 있대 yup

https://www.npmjs.com/package/yup

yarn add yup
yarn add @hookform/resolvers

- resolver에는 yup이외에도 다른 검증 라이브러리를 사용 가능

검증 라이브러리로 검증을 우리가 하는 것이 아니라 form 과 함께쓰이며 검증을 대신해주는 라이브러리

이렇게 사용 할 예정

4.재사용을 위한 공통컴포넌트 만들자 Common-Component

storybook
직접 인풋이나 버튼을 하나하나 만드는 것이 아니라
공통 컴포넌트로 미리 만들어두고 가져와서 사용

만약 날씨나 계절별로 다른 스타일을 적용하고 싶다면
가져오는 폴더만 변경되면 되게 하는 것

const schema = yup.object({
  email: yup
    .string()
    .email("이메일 형식이 적합하지 않습니다")
    .required("이메일은필수 입력사항입니다"),
    // 문자형인지 보고 필수입력값으로 등록
  Password: yup
    .string()
    .min(4, "비밀번호는 최소 4자리 이상 입력해주세요")
    .max(15, "비밀번호는 최대 15글자입니다")
    .required("비밀번호는 필수 입력사항입니다."),
  
});
// 문자형이고 최소/최대 입력값과 필수입력값으로 등록
// 조건들을 넣고 formState로 오류 시 발생할 것들을 등록 할 수 있음
// 밑에 메세지를 등록할것으로 옵셔널체이닝 했기때문에
// 메세지에 나올 내용들을 넣어둠

-에러가 있을수도 있고 없을수도 있기때문에 옵셔널 체이닝을 사용

  • 버튼을 활성화 하는건 formState의 isValid를 사용

0개의 댓글

관련 채용 정보