다음에 또 요청할 수 있기 때문에 여러컴포넌트에서 재사용할 수 있도록 글로벌 스테이트에 저장했다.
그렇게 되면 바로 API 요청하지 않고 글로벌 스테이트에서 확인 후 가져온다.(요청 수 감소 목적)
fetch-policy!!DB에 추가됬는데 화면에 안보여서 refetch라는 걸 했고
조회된 목록을 다시 조회해서 변경했다.useQuery()는 수행 후 cache-state에 저장되는데,
refetch를 사용하게 되면 새롭게 다시 받아오기 때문에 비효율 적인 구조가 되므로 좋은 방법이 아니다.따라서 가급적 요청을 줄이기 위해 cache-state 직접 업데이트 해보기로 한다.
[실습 section 26]
import { useQuery, gql, useMutation } from "@apollo/client"; import type { IQuery, IQueryFetchBoardsArgs, } from "../../../src/commons/types/generated/types"; const FETCH_BOARDS = gql` query fetchBoards($page: Int) { fetchBoards(page: $page) { _id writer title contents } } `; // 캐시에 저장되는 데이터와 요청 후 받아오는 값이 일치되야 한다. const CREATE_BOARD = gql` mutation createBoard($createBoardInput: CreateBoardInput!) { createBoard(createBoardInput: $createBoardInput) { _id writer title contents } } `; const DELETE_BOARDS = gql` mutation deleteBoard($boardId: ID!) { deleteBoard(boardId: $boardId) } `; export default function StaticRoutingPage(): JSX.Element { const { data } = useQuery<Pick<IQuery, "fetchBoards">, IQueryFetchBoardsArgs>( FETCH_BOARDS ); console.log(data); const [나의함수] = useMutation(CREATE_BOARD); const [deleteBoard] = useMutation(DELETE_BOARDS); interface IPrev { // _id: string; //에러남? 왜? __ref: string; } const onClickDelete = (boardId: string) => () => { void deleteBoard({ variables: { boardId, }, // refetchQueries: [{ query: FETCH_BOARDS }], //성능 비효율적 update(cache, { data }) { // 캐시를 수정한다는 뜻의 cache.modify cache.modify({ // 캐시에있는 어떤 필드를 수정할 것 인지 key-value 형태로 적어준다. fields: { fetchBoards: (prev: IPrev[], { readField }) => { //여기서 prev는 fetchBoards! const deletedId = data.deleteBoard; // 삭제완료된 ID // const fileterdPrev = prev.filter((el) => el._id !== deletedId); //el은 게시글 하나씩 삭제된 아이디가 맞는지 확인하여 아닌애들 필터링(9개) const fileterdPrev = prev.filter( (el) => readField("_id", el) !== deletedId ); //el은 게시글 하나씩 삭제된 아이디가 맞는지 확인하여 아닌애들 필터링(9개) return [...fileterdPrev]; //삭제된 아이디를 제외한 나머지 9개를 리턴한다. }, }, }); //삭제된 아이디 반환 }, }); }; const onClickSubmit = () => { void 나의함수({ variables: { createBoardInput: { password: "1234", writer: "writer", title: "title", contents: "contents", }, }, // refetchQueries:[{query:FETCH_BOARDS}] // 비효율적 update(cache, { data }) { //구조분해할당 data는 11개의 데이터 //globalstate의 cache임 (cache에는 기존의 데이터) cache.modify({ fields: { fetchBoards: (prev) => { //fetchBoards에 있는 것이 return값으로 수정됨 10개 데이터를 prev로 받아옴 return [data.createBoard, ...prev]; //fetchBoards 11개로 업데이트 }, }, }); }, }); console.log(result); }; return ( <div> {data?.fetchBoards.map((el) => ( <div key={el._id}> <span style={{ margin: "10px" }}>{el.title}</span> <span style={{ margin: "10px" }}>{el.writer}</span> <button onClick={onClickDelete(el._id)}>삭제</button> </div> ))} <button onClick={onClickSubmit}>등록</button> </div> ); }
캐시를 직접 수정하기 위해update(){}
라는 기능을 이용한다.update 기능을 사용할때 파라미터로 데리고 온
cache
는apollo-cache-state에 있는 global state
!그리고
업데이트 된 결과
는 파리미터의{data}
에 들어오게 된다.
el._id
로 해주지 않는 이유는,
ref를 따라가야 나오기 때문임!
id에는 ref가 들어가 있음!readField사용하면 ref를 참조해서 id를 뽑아올 수 있다.
state 바뀌어서 화면이 바뀜
추가적인 요청이 필요없음!
✔️ fields의 prev와 return값
- fields는 캐시에 있는 어떤 데이터를 수정할 것 인지를 알려준다.
- fields 의 prev : 이전데이터를 불러온다.
- fields의 return값 : 이전 데이터를 return 값으로 바꿔준다 업데이트 된 결과가 {data} 이므로 결국 {data} 내부의 값이 된다
하지만 상황에 따라 다르다.
작은 규모의 서비스의 경우에는 굳이 API요청을 줄이기 위해
소스코드를 줄일 필요가 없다.
이런 걸 오버엔지니어링이라고 함!
굳이 필요하지 않은데 최적의 성능을 뽑으려고 하는 것큰 규모의 서비스인 경우에는 API요청을 줄이는 것이
비용면에서도 효율적이다!