[TIL 0411] 글로벌 스테이트

zitto·2023년 4월 11일
0

TIL

목록 보기
40/77
post-thumbnail

💡 글로벌 스테이트

: 전역에서 사용할 수 있는(여러
컴포넌트에 사용되는) state
하나만 만들어서 모든 컴포넌트에 사용가능!

useQuery에서 받아온 데이터를 props drilling을 하지 않아도 되고 굉장히 편리해진다.

전역상태관리(global state) 툴로는 context-Api, Redux, Recoil등이 있다.

✅ fetchPolicy

apollo-client의 고급 기능을 먼저 살펴보자면,
여러 컴포넌트가 있고, 여러 컴포넌트들이 공유할 수 있는 global state가 있다고 할때,

apollo-client로 global state를 만들게되면 Apollo-Cache 라는곳에 저장된다.

만일 2번 컴포넌트에서 useQuery를 해오게 되면 useQuery를 해서 받아온 데이터가 Apollo-Cache에 저장된 후 컴포넌트로 들어오게 된다.

이후에 3번 컴포넌트에서 같은 데이터를 요청하게 되면,
Apollo-Cache 에 먼저가서 데이터가 있는지 확인하고
없으면 백엔드에 요청을
있으면 백엔드에 요청을 하지 않고 컴포넌트로 바로 보내주게 된다.

이를 Apollo-client의 fetchPolicy(fetch 정책)라고 한다.

  • fetchPolicy의 기능
    “cache-first” default → 캐시에 있는지 먼저 확인
    “network-only” → 캐시에 있든 없든 무조건 백엔드에 요청
    (새로고침 전까지 기존거 보게끔 하면 비용절감 - sns서비스 같은데 유용함)


    [실습]
export default function StaticRoutingPage(): JSX.Element {
  const { data } = useQuery<Pick<IQuery, "fetchBoards">, IQueryFetchBoardsArgs>(
    FETCH_BOARDS,
    {
      fetchPolicy: "network-only", //이전경험 상관없이 무조건 새거 받아옴,  default는 cache-first
  • cache-first
    글로벌스테이트에 있는 걸 임시저장한다고 본다.
    글로벌스테이트에 저장하는 용도는 서버데이터 캐싱을 위한 목적이 대부분!

✅ Recoil

프론트에서 관리하는 데이터라고 해봤자 많은 부분을 차지하지 않을 텐데 Redux를 사용하기에는 너무 헤비하여 어렵고 비효율 적이기 때문에 recoil을 사용한다.

  • 설치명령어: yarn add recoil 3중에 하나를 선택해서 쓰는게 트렌드!

  • app.tsx 파일에서 세팅!

import { RecoilRoot } from "recoil";
export default function App({ Component }: AppProps): JSX.Element {
  return (
    <div>
      <RecoilRoot>
        <ApolloSetting>
          <>
            <Global styles={globalStyles} />
            <Layout>
              <Component />
            </Layout>
          </>
        </ApolloSetting>
      </RecoilRoot>
    </div>
  );
}
  • src -> commons -> stores -> index.ts
// globalstate
import { atom } from "recoil";
export const countState = atom({
  //고유함. 딱 하나
  key: "countState",
  default: 0,
});

Recoil에서는 Atom으로 state의 일부를 보여준다.

그리고 컴포넌트들은 자신이 필요한 Atom을 참조하고 있다.
따라서 자신이 참조하고 있는 Atom에 변화가 있으면,
해당 atom을 참조하는 모든 컴포넌트에서 리렌더링
이 일어난다.

Recoil은 결국 context-api의 단점을 보완한 상태관리 라이브러리 이기때문에 context-api를 기반으로 하고다!


[실습]

  • recoil.tsx
import { useState } from "react";
import { useRecoilState } from "recoil";
import { countState } from "../../../src/commons/stores";
import Child1 from "../../../src/components/units/22-global-state/child1";
import Child2 from "../../../src/components/units/22-global-state/child2";
export default function GlobalStateWithRecoilPage(): JSX.Element {
  // const [count, setCount] = useState(0);
  const [count, setCount] = useRecoilState(countState);
  const onClickCountUp = (): void => {
    setCount(count + 1);
  };
  return (
    <div>
      <div>페이지의 카운트:{count}</div>
      <button onClick={onClickCountUp}>카운트 올리기!</button>
	  =====================================================
      <Child1 />
      =====================================================
      <Child2 />
    </div>
  );
}
  • child1.tsx
import { useState } from "react";
import { useRecoilState } from "recoil";
import { countState } from "../../../commons/stores";
export default function Child1(): JSX.Element {
  const [count, setCount] = useRecoilState(countState);
  const onClickCountUp = (): void => {
    setCount(count + 1);
  };
  return (
    <div>
      <div>자식1의 카운트:{count}</div>
      <button onClick={onClickCountUp}>카운트 올리기!</button>
    </div>
  );
}
  • child2.tsx
import { useState } from "react";
import { useRecoilState } from "recoil";
import { countState } from "../../../commons/stores";
export default function Child2(): JSX.Element {
  const [count, setCount] = useRecoilState(countState);
  const onClickCountUp = (): void => {
    setCount(count + 1);
  };
  return (
    <div>
      <div>자식2의 카운트:{count}</div>
      <button onClick={onClickCountUp}>카운트 올리기!</button>
    </div>
  );
}


profile
JUST DO WHATEVER

0개의 댓글