24일) useQuery로 바로 안불러오고 useApolloClient로 axios처럼 원하는 위치에서 data 불러올래요! YUP! react HOOK! code camp FE 6기

김아름·2022년 4월 14일
1

코드캠프6기

목록 보기
23/36
post-thumbnail

흐름을 잘 이해하기위해 수업끝나고 그려본 코드의 숲(?)이 오늘의 썸넬..!

  • 오늘 수업이 끝나면 알게될 것들 !
    오늘은 여러가지 쿼리방식을 배웠습니다!
    그 중, 컴포넌트가 열리면 실행되는 useQuery와 달리 원하는 시점에 실행 해줄 수 있는 useLazyQuery와 axios처럼 원하는 위치에서 받을 수 있게 도와주고 결과 값을 내가 원하는 상자에 담아줄 수 있는 useApolloClient를 알아봤죠!
    위 특징으로 본다면 useLazyQuery는 useQuery와, useApolloClient는 axios와 닮았었습니다!
    우리는 원하는 시점에 query요청을 보낼 수 있는 useApolloClient의 특징을 활용하여 fetchUserLoggedIn 결과값(UserInfo)을 GlobalState에 담아주는 실습을 진행했죠!
    이를 위해서 우리는 onClickLogin 안에서 client.query({})로 요청을 보냈습니다!
    여기서 중요한 포인트가 있었죠! 어느 정보를 불러올지 인증 정보를 함께 보내야 한다는 것! 따라서 client.query의 context의 headers 내부에 Authorization 정보를 함께 첨부해 보내주었고, 그 결과값을 GlobalContext 안 setUserInfo에 담아 주었습니다! refreshToken을 배울때까지의 임시방편이지만 담아준 userInfo를 localStorage에 담아주었죠! JSON.stringfy를 활용해 setItem해주었습니다!
    폼 라이브러리는 여러 종류가 있었죠!
    react-form, redux-form, formik, react-hook-form 등...
    폼 라이브러리란 그동안 우리가 스프레드 연산자를 쓰고, onChangeInput, state 등을 만들어서 직접 관리했던 폼들을 미리 만들어 놓고, 라이브러리 형태로 제공해 주는 것이 폼 라이브러리였습니다.
    그 중, 최근에 함수형 컴포넌트에서 가장 많이 사용되는 폼 라이브러리가 바로 react-hook-form 입니다!
    react-hook-form과 함께 제어(controlled)/비제어(uncontrolled) 컴포넌트도 알아봤습니다!
    제어 컴포넌트는 state 등 입력값에 대한 변경 사항에 대한 정확도가 높다는 장점이 있었습니다! 따라서 중요도가 높은 내용 입력에 적합했죠! 다만 변경 시 마다 다시 렌더링 되기 때문에 느리다는 단점이 있었습니다! 지금까지 우리가 사용한 방식은 제어 컴포넌트였죠!
    하지만 react-hook-form은 비제어 컴포넌트 방식이기 때문에 변경 사항에 대해 100% 정확도는 보장할 수 없었습니다! 그렇지만 입력 시 마다 다시 렌더링 하는 과정이 없기 때문에 빠른 장점이 있었습니다!
    React-hook-form을 사용한 작성은 지금까지 만들었던 방식과는 조금 달랐습니다! 페이지 전환 없이 데이터만 주고 받는 ajax(비동기 javascript통신)방식이라 했죠!
    입력값을 받을 Input태그들을 form이라는 태그로 감싸주었습니다!
    그렇다면 input에 대한 처리는 어떻게 바뀌었는지 기억나시나요? useForm()으로 state를 등록하는데 필요한 모든 기능(onChange,onClick, onError 등)이 담겨있는 register를 가져와 input에 스프레드 시켜주었습니다! 그냥 스프레드만 시켜주는 것이 아니였죠! register(“”)안에 input의 이름(구분)도 넣어주었습니다! 이렇게 담긴 값들 혹은 Error등 은 formState에 담겼습니다!
    form태그에는 onSubmit()이라는 함수를 연결 시켜주었고, 이렇게 감싸준 form 태그 내부에 button을 넣어주었습니다!
    이 버튼은 기본값이 submit이기 때문에 버튼을 누르면 이 버튼을 누르게 되면 form에 연결된 onSubmit에 담은 함수가 실행이 되었죠!(버튼의 default type은 submit이기 때문에 다른 기능이 들어간 버튼을 만들어 추가적으로 넣어줄 때는 type을 button으로 주어 사용해야 했습니다) 하지만 그냥 함수만 담아 실행할 수 없었습니다! 우리가 등록한 데이터들을 함께 담아서 실행해야 하기 때문에 함수를 handleSubmit으로 감싸주었던 점! 기억하시죠!? useForm({})안에 들어가는 mode: “onChange” 는 변동을 확인하는 역할인데 컴포넌트 분리로 인한 register 연결유지를 위해 사용합니다!
    다음으로, 검증 라이브러리가 있었습니다. 오늘 배운 것은 yup이었죠!
    yup을 사용하여, 기존의 정규표현식 또는 length를 기준으로 한 최소/최대글자수, 등의 조건을 아주 쉽게 추가할 수 있었습니다.
    또한, 검증 라이브러리와 폼 라이브러리는 서로간에 독립적으로 사용될 수 있으므로, 반드시 react-hook-form과 yup을 같이 사용해야만 하는 것은 아니었어요! (yup은 formik 등 다른 라이브러리에서도 함께 사용 가능합니다)
    react-hook-form 과 함께 사용하기 위해 yarn add @hookform/resolvers yup 를 사용해 추가해줬죠!
    사용하기 위해 @hookform/resolvers/yup/ 내부의 yupResolver를 Import 시켜줬습니다!
    여기서 yupResolver()를 useForm({}) 내부 resolver에 넣어주었고 규칙 설정을 위해 schema를 만들어 yup.object().shape({}) 설정을 해주었습니다. 이 안에는 우리의 입력값의 규칙을 정해 줄 수 있었습니다! 이렇게 만든 schema를 yupResolver()안에 넣어주어 React-hook-form과 연결시켜주었죠! 끝으로 formState안에는 isValid라는 값이 있다고 했습니다! 이 값을 활용하면 값이 모두 올바르게 들어갔는지 검증할 수 있었죠!?
    마지막으로, 인풋박스와 버튼 등은 각각의 페이지에서 직접 작성하지 않고, 따로 만들어 놓고 import하여 사용했습니다.
    이러한 컴포넌트를 공통컴포넌트(Common components)라고 합니다.(ex.크몽 스토리북)
    이렇게 함으로써 얻게 되는 장점은 특별한 날, 또는 다른 이유로 인해서 전체적인 화면 분위기를 변경해야 할 때, common 컴포넌트를 변경함으로써 모든 버튼에 전체 적용이 가능하도록 만들었었죠!
    만약, 페이지별로 각각 만들었다면 변경하기도 힘들고, 다시 되돌아오기도 굉장히 힘들어 집니다.
    여러분들이 어떠한 회사에 가시더라도 공통 컴포넌트는 사용하게 될 겁니다!
  • 오늘의 알고리즘 문제 !
    마지막에 갓범수님한테 int의 범위에 대해 듣게되고 맞추었다...!
    숫자의 타입 정리해놓자.?

Number.MAX_SAFE_INTEGER
int타입의 유효한 숫자 범위를 알려주는것
int는 2의 53제곱 -1까지만 유효하다...!
그래서 안쪽에 이렇게 나눠줘도 된다 !

((a%c) + (b%c))%c 는
(a+b)%c 와같다
<생각해보쟈>
Reduce를 사용한 풀이

function solution(n){
  let prev = 0; //0번째 피보나치 수의 결과 
  let next = 1; //첫번째 피보나치 수의 결과
  let sum = prev + next 
  const answer = new Array(n-1)
  								.fill(1)
  								.reduce((acc) =>{
                    sum = (prev + acc ) %1234567 //피보나치수
                    prev = acc; //n-2
                    next = sum; 
                    return sum
                  },sum)
  								return answer
}
  • 오늘 배울것

-useQuery

  • 요청과 그림을 그려주는 부분(리렌더링) 모두 자동

    화면이 그려질때 요청이가고 , data로 받아오고 자동으로 그 데이터를 가지고 화면에 그리게 된다

-useLazyQuery

  • 요청은 내가 하고싶을때 가능, 리렌더링 자동

    함수를 실행할때 요청이 날아가서, 받아지게 되면 그때 data가 들어오는것
    useQuery랑 같은데 실행을 원할때 (함수실행할때) 할수 있다

-useApolloClient

  • 요청도 수동으로 보내고, 리렌더링도 수동

    데이터까지만 받아와주고 , 받아온애를 그리는건 내가 해야한다
    axios랑 비슷한데 axios 쓸때 특정한 변수에 저장한 다음에 썼던것 기억 ! axios를 graphql로 쓴다고 생각!


    어제했던 로그인페이지, 성공메인 페이지 부분에서
    성공메인 페이지의 fetch쿼리를 recoil로 빼서 쓰면 더 편하지 않을까!
    정보는 사이트별로 계속 불러와야하니까 !
  1. 그러면 로그인 버튼 누르는 순간 로그인하고, 유저정보까지 recoilState
    에다가 저장해놓고 다른 사이트들에서는 한줄씩만 import해서 쓰자 !

  2. usequery는 자동으로 가고 오는거여서 안된다고 했지
    그래서 useapolloclient를 사용해보겠어
    로그인 페이지에서
    const client = useApolloClient() 똑같이 해주고
    client가 axios라고 생각해서 써보자

    쿼리문(gql) 불러와주고

    client.query({
    query: FETCH_USER_LOGGED_IN
    })
    이렇게 쿼리를 보내면 될까?..

로그인토큰을 같이 보내야 특정유저의 정보가 반영이 되겠지 !

(우리 이거 어제배운 토큰 로컬스토리지 저장했기 때문에 쓸수 있어 !)
그래서 우리가 어제 bearer 방식 써서 저장해서 보내준거고,,

context는 http같은 추가적인 부분의 요청을 보낼때 쓰는것

        ```
  client.query({
        query: FETCH_USER_LOGGED_IN,
        context:{
            headers: {
                Authorization: Bearer ${accessToken},
            }
        }
    })```

이렇게 보내주고 담아주자

그럼 저 드디어 받아온 유저정보(resultUserInfo)를 변수에 담아서 recoilstate에 담아주자


localStorage.setItem("accessToken",accessToken)
localStorage.setItem("userInfo",userInfo)
똑같이 써주면 userInfo는 객체라서 안된다
문자열로 바꿔서 저장하고 그 문자열을 객체로 바꿔서 사용해야한다
localStorage.setItem("userInfo",JSON.stringify(userInfo))
문자열로 저장해주자


잊지말고 아폴로 설정가서 useEffect 해주자
(새로고침하면 날아가는거 말고 넣어주는거)


const userInfo = JSON.parse(localStorage.getItem("userInfo"))
객체로 바꿔서 넣어줘야하기때문에 이렇게 useEffect에 넣어주고
recoilstate 작성해주고!
흐름 파악하게 그림을 보면서 파악하자 !

후 수고했다 이제 브라우저로 가서 실행해보면
내가 정해준 userinfo까지 localstorge에 저장된걸 볼수 있다

form 태그와 button 타입


^ 예시 코드 기준으로 설명해보면
form 안에 있는것들을 대상으로
submit형식과 reset이 진행되는거고
원래 버튼누르면 함수가 실행되는 기능은
type이 button인 onclick한 함수만 실행된다 (나만의 버튼)
타입을 적지 않으면 default로 submit이 실행이 된다


form onsubmit에서는 buttob=button 해줘야 submit이 실행이 되지 않는다
form이 자동화된 라이브러리가 많다
react-form
redux-form
react-hook-form(가장간단)(훅폼이니까 함수형?)
formik...(가장유명)(클래스컴포넌트주로)

- 아주아주 친절한 react-hook-form

https://react-hook-form.com/
렌더카운트가 1이라고 자랑하는 모습이다
퍼포먼스가 훨씬 빠르다

어떻게 하길래 리렌더링이 안일어나지 ?

->컴포넌트에는
- 제어 컴포넌트 ( 내가 작성하는것마다 state를 줘서 작성할때마다 데이터가 저장)
일반 라이브러리가 사용하는것

- 비제어 컴포넌트 (작성을 input에 해도 state에 바로 저장 안하고 나중에 콕찍어서 가져오는것 )
리액트 훅 폼이 쓰고 있는거다 그래서 리렌더가 일어나지 않는다

  • 우리는 공식 홈페이지의 advanced를 자주 볼 예쩡!


    register 안에 onchange랑 저장하는 state랑 다 있어서
    ...register로 불러오고 (이름) 적어주면 된다
    그럼 그 값들을 함수 안에서 써주려면 handlesubmit함수를 추가해주면
    우리가 지금 입력한 state들이 함수 안으로 들어간다
    그러면 이렇게 onchange~setstate~ input에 하나하나 적어줄 필요없이
    form 태그로 16줄만에 완성 !!!
    그리고 비제어 컴포넌트라서 리렌더가 글씨 쓸때 한번도 일어나지 않는걸 볼수 있다
  • 우리 에러뜨는거 빨간색 줄! 조건문 넣어서 아니면
    박스 띄워줬던 힘든것들! 그것도 폼이 있어 !

에러 검증해주는 라이브러리 yup !


yup에서 이름은 스트링이고,
나이는 숫자고 18넘어야하고.. 이렇게 간단하게 쓰면 에러 조건문 달필요없이 yup라이브러리를
이용해 검증해서 error 띄울수있다

얘는 독립적인 라이브러리라서
react -hook-form 혹은 formit이랑 같이 쓰는건데
리액트훅폼가면 yup같이쓰기가 따로 있다 ! (schema validation)
const {register, handleSubmit} = useForm({
여기에 활용할 리솔버를 써주면 된다

  • 같이 쓰는 모습 resolver: yupResolver(schema)
    다른거 쓰고싶으면 리솔버에 다른거 쓰면 된다

    자자 설치가자
    yarn add @hookform/resolvers yup
    두개 한방에 설치


    yup에러를 가져다가 쓴모습

    이메일 검증(골뱅이와 . 과 문자형식은 yup에서 정해놓은규칙가져다가 쓴거!


    나중에는 이 모든걸 컴포넌트형태로 만들어서.. story-book을 만든다
    대표적인 크몽 스토리북 !


    요런 스토리북은 프론트엔드 개발자가 만들어서 디자이너와 협업하는건데, 우리 회사엔 이런디자인들 있으니까 봐보시고 디자인하세요~ 하고 우리가 페이지를 만들어서 주소 보내주면 된다



    yarn add storybook 이 있네..?!


    컴포넌트로 빼서 쓴부분
    props와 쓰는 방법들 정리하자
profile
SUNNY SUMMER ! 같이 일하고 싶은 개발자 여름이의 초심을 잃지 않기 위한 주절주절 부트캠프 시절 블로그.

0개의 댓글