React

이번주 커리큘럼

오늘 수업내용

Destructuring(비구조화 할당 = 구조분해 할당)

name, age, school 라는 각 변수를 생성한 뒤,
child.name, child.age, child.school의 값을 할당하고 싶을 때

세줄 말고 한 줄에 한 번에 할 수 있는 방법은? 구조분해할당

( {} 중괄호인 이유는? 가지고오려는게 객체이기 때문에 ,,! )

useQuery 함수 예시 useQuery의 return 값이 data, loading 등의 객체 이기 때문에 여기서도 { } 객체로 !

배열의 구조분해할당 예시 대괄호인 이유는?! 가지고오려는게 배열이기 때문에 !

useState 함수 예시

구조분해할당 실습

useQuery

const {data} = useQuery(profile) 
// useQuery의 결과가 객체여야 한다(왜냐면 profile이 객체니까) 
// 그리고 그 객체 안에 data라는 키와 해당 값이 들어있어야 함 ! 그래야 Data를 뽑아서 객체를 만들 수 있으니까 

실행 결과

useState

실행 결과

객체 구조분해할당의 경우 순서 말고 이름이 중요하지만, 배열의 경우 해당 이름이 없기 때문에 순서가 중요하다 !

=> useState를 배열로 리턴하는 이유? state 이름을 변경해서 사용하기 편리하기 때문에

구조분해할당 하지 않고 그냥 냅다쓰는 방법

Custom Hooks

custom hook은? 이름 그대로 개발자가 스스로 커스텀 한 훅
use 로 시작하는 함수.. 라고 생각하자!

Custom hooks 사용시 주의사항

사용하게되면 함수 네이밍에 use를 사용해주는게 관례 (안붙여도 작동은 하는데 에러 핸들링이 어려워질 수 있음)

Custom hooks 만들기

// custom hook 만들기

import {useState} from react

// 커스텀 훅 함수 
function useFetch(url) {
  const [data, setData] = useState([])

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(resJson => setData(resJson))
  }, [url])

	// 커스텀 훅의 return부분 입니다.
  return data
}
// useAuth 함수 만들기
import { useRouter } from "next/router";
import { useEffect } from "react";

export function useAuth() {
  const router = useRouter();

  useEffect(() => {
    if (!localStorage.getItem("accessToken")) {
      alert("로그인 후 이동 가능합니다");
      router.push("/23-04-login-check");
    }
  }, []);
}
// custom hook은? use로 시작하는 함수
// custom hook 만들기

import { useAuth } from "../../src/components/commons/hooks/useAuth";

//useAuth import 해서 권한점검하기

export default function CustomHooksUseAuthPage() {
  useAuth();

  return <div>프로필 페이지 입니다</div>;
}

custom hook은 컴포넌트가 아닌 함수이기때문에 return 부분이 JSX가 아님

=> 여러 컨테이너에서 공통적으로 사용되는 로직들은 custom hook으로 빼주고, 코드 길이를 줄여 효율적으로 사용할 수 있음

ex) router push 버튼 같은거 오백개 만들지 말고 custom hook으로 만들어주기

refetch의 문제점과 개선 방법

지금까지는 등록/삭제 이후 refetch를 통해 목록을 업데이트 했지만, 이제부터는 refetch를 하지 않고 apollo-cache-state를 직접 업데이트 하는 방법을 사용할 것!

데이터의 두 번째 게시물을 삭제한다고 칠 때 삭제 버튼을 누르면 삭제 1.mutation이 날아가면서 2.삭제 리패치가 되게 된다 그렇게 되면 1,2 단계를 거치기 때문에 서비스 규모가 커질 시 네트워크 부하가 많이 된다 ! 그래서
그렇게 하지 않고 1단계만에 될 수 있도록 글로벌 스테이트(apollo-cache-state)에 가서 2번째 것을 강제로 지워 고치게 만드는 것(스테이트이기 때문에 강제로 리랜더가 일어나게 된다) => 두번의 네트워크 요청을 한 번으로 줄임

apollo-cache-state

const onClickDelete = (boardId: string) => async () => {
    // HOF 사용시 async 는 await 의 가장 가까운 함수 앞에 걸어준다
    await deleteBoard({
      variables: {
        boardId,
        // key 와 value 가 같으니까 밸류 생략
      },
      // refetchQueries: [{}],
      update(cache, { data }) {
        // 추가적인 네트워크 요청 없이 state 업데이트 요청 가능
        cache.modify({
          // cache 를 직접 수정하기
          // 일단 deleteBoard 실행 시키고 응답 받은 뒤 실행됨 !
          fields: {
            // 어떤 쿼리 를 수정할건데? => fetchBoards
            fetchBoards: (prev, { readField }) => {
              // 게시물 10개가 있으면 삭제할 게시물 말고 나머지 9개 만들어서 리턴해주면 됨
              const deletedId = data.deleteBoard;
              // 삭제될 게시물을 변수에 담아주기
              const filteredPrev = prev.filter(
                (el: any) => readField("_id", el) !== deletedId
              );
              // 각각의 게시물 중 deletedId가 아닌 9개만 필터링 해주기
              // 근데 prev 안에 객체형태로 들어오지 않아서 el._id 로 사용해 줄 수가 없음 => 꺼내주는 도구 readField 이용
              // readField 에 있는 id 를 사용해주세요! 하고 꺼내기
              return [...filteredPrev];
              // 리턴되는 값으로 fetchBoard 가 바뀐다 (직접적인 네트워크 요청 없음)
            },
          },
        });
      },
    });
  };

  const onClickSubmit = async () => {
    await createBoard({
      variables: {
        createBoardInput: {
          writer: "이망고",
          password: "1234",
          title: "망고망고제목",
          contents: "망고망고망고내용",
        },
      },
      // refetchQueries: [{}],
      update(cache, { data }) {
        // 추가적인 네트워크 요청 없이 state 업데이트 요청 가능
        cache.modify({
          // cache 를 직접 수정하기
          fields: {
            // 어떤 쿼리 를 수정할건데? => fetchBoards
            fetchBoard: (prev) => {
              // 글로벌 스테이트의 fetchBoard 라는 키에 데이터가 저장되어 있는데,
              // 기존에 있던 10개에 방금 등록한 한개 추가해서 보내주기
              return [data.createBoard, ...prev];
              // 방금 등록한 게사물을 맨 앞에 보내주고 그 뒤에 기존에 있던 게시물 10개 !
              // 리턴되는 값으로 fetchBoard 가 바뀌게 된다 (직접적인 네트워크 요청 없음)

Rest 파라미터

특정 객체에서 지우고싶은 데이터가 있을 때
delete를 사용해서 원본은 건드리는 것은 바람직하지 못함 !

=> 따라서 원본을 건들이지 않고 삭제하기 위해 rest 파라미터를 이용(구조분해할당과 함께)

const { money, hobby, ...rest} = child

이렇게 적으면 rest 부분에는 money와 hobby를 제외한 모든게 들어감

++++
State 구조분해할당 참고

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

0개의 댓글