redux 를 사용하지 않고 global state를 관리할 방법을 찾다가ApolloClient를 이용한 local state management를 알 게 되었다.
GraphQLServer와 동일하게 client에서도 cache를 사용해 관리하는 방법도 있고 ApolloClient 버전 3 부터 제공되는 Reactive variables 를 사용하는 방법도 있다.
// cache.js
import { makeVar } from "@apollo/client";
export const usersVar = makeVar([]);
// 함수처럼 호출
// 인자에 아무것도 넘기지 않으면 기존에 있던 값을 반환
const users = usersVar();
// 인자에 값을 넘기면 기존 값을 대체
const newUser = "mina";
usersVar([...usersVar(), newUser]);
// ReactiveVarExample.js
import React from "react";
import { useReactiveVar } from "@apollo/client";
import { usersVar } from "../apollo/cache";
export default function ReactiveVarExample() {
// useReactiveVar로 usersVar를 넘겨야 변경사항을 감지하여 리랜더링해준다.
const users = useReactiveVar(usersVar);
return (
<div>
<h2>Use Reactive Variable</h2>
<ul>
{users.map((username, index) => (
<li key={index}>{username}</li>
))}
</ul>
</div>
);
}
@client
를 붙여줘야 함!// typeDefs.js
import { gql } from "@apollo/client";
export const typeDefs = gql`
extend type Query {
users: [User]!
}
extend type User {
name: String!
}
`;
// query.js
import { gql } from "@apollo/client";
export const GET_USERS = gql`
query getUsers {
users {
name @client
}
}
`;
import { ApolloClient, InMemoryCache } from "@apollo/client";
import { typeDefs } from "./typeDefs";
import { GET_USERS } from "./query";
const cache = new InMemoryCache();
// 초기값 지정
cache.writeQuery({
query: GET_USERS,
data: {
users: [],
},
});
// client 전용 쿼리를 사용하기 위해 typeDefs 인자로 넘겨주기
export const client = new ApolloClient({
uri: "https://48p1r2roz4.sse.codesandbox.io",
cache,
typeDefs,
});
const client = useApolloClient();
// 기존 데이터 불러오기
const data = client.readQuery({ query: GET_USERS });
// 새 데이터 추가하기
client.writeQuery({
query: GET_USERS,
data: {
users: [...data.users, createUser(inputRef.current.value)],
},
});
// __typename을 반드시 지정해야 에러가 나지 않는다.
// typeDefs에서 type을 찾을 때 __typename을 보기 때문
const createUser = (name) => {
return {
name,
__typename: "user",
};
};