GraphQL, React로 movie web 만들기

김지원·2021년 2월 5일
0

Apollo

: Apollo는 GraphQL API를 사용하기 좋은 방법이다.
REST API는 URL로 가서 JSON을 받아오지만
GraphQL은 query를 보내거나 mutation을 보내야한다.

설치
npxcreatereactappApollomovienpx create-react-app Apollo_movieyarn add styled-components react-router-dom apollo-boost @apollo/react-hooks graphql

Route 설정

src/components/App.js

import React from "react";
import {HashRouter as Router, Route} from "react-router-dom";
import Detail from "../routes/Detail";
import Home from "../routes/Home";

function App() {
  return (
<Router>
    <Route exact path="/" component={Home}/>
    <Route path="/:id" component={Detail}/>
</Router>
  );
}

export default App;

src/routes/Detail.js

export default () => "Detail";

src/routes/Home.js

export default () => "Home";

apollo-boost

: apollo-boost는 GraphQL Yoga처럼 이미 모든 걸 다 설정해 둔 package이다.
GraphQL Yoga가 바로 쓸 수 있게 준비를 다 해둔 server고 반대로 apollo-boost가 client 쪽이다.

src/apollo.js

import ApolloClient from "apollo-boost";

const client = new ApolloClient({
    uri: "http://localhost:4000/"
});

export default client;

index.js
ApolloProvider로 감싸준다.

import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import {ApolloProvider} from "@apollo/react-hooks";
import client from "./apollo";

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);

GET MOVIE Query

useQuery를 사용하여 data 가져오기

fetch나 JSON 같은 부분들을 전혀 하지 않고 useQuery를 사용하여 data를 가져올 수 있다.

src.routes/Home.js

import React from "react";
import {gql} from "apollo-boost";
import {useQuery} from "@apollo/react-hooks";
import styled from "styled-components";
import Movie from "../components/Movie";

const GET_MOVIES = gql`
    {
     movies{
        id
        medium_cover_image
        }
    }
`
export default () => {
    const {loading, data} = useQuery(GET_MOVIES);
    return (
        <Container>
            <Header>
                <Title>Apollo movie</Title>
                <Subtitle>I Love GraphQL</Subtitle>
            </Header>
            {loading && <Loading>Loading...</Loading>}
            {!loading &&
            data.movies &&
            data.movies.map(m => <Movie key ={m.id} id={m.id}/>)
            }
        </Container>
    )
}

src/components/Movie.js

import React from "react";
import {Link} from "react-router-dom";

export default ({id}) => (
    <div>
        <Link to={`/${id}`}>{id}</Link>
    </div>
);

query에 variable이 있을 때 (예를 들어서 id) 그러면 그 query의 이름을 적어야 한다.
(Apollo, React, GraphQL, React Apollo을 위한 이름)
query에서 이름부분은 Apollo를 위한 것이다. Apollo가 변수의 type을 검사하도록 도와준다.
안에 movie(id){} 부분은 서버로 가는 query이다.

src/routes/Detail.js

import React from "react";
import {useQuery} from "@apollo/react-hooks";
import { useParams } from "react-router-dom";
import { gql } from "apollo-boost";

const GET_MOVIE = gql`
    query getMovie($id: Int!) {
    movie(id: $id){
        id
        title
        medium_cover_image
        description_intro
        }
    }
`;
export default () => {
    let {id} = useParams();
    const {loading, data} = useQuery(GET_MOVIE, {
        variables: {id: parseInt(id)},
    });
    if(loading){
        return "loading";
    }
    if(data && data.movie){
        return data.movie.title;
    }
};

React Apollo cache

한번 눌렀던 id를 다시 누르면 loading이 뜨지 않고 바로 제목이 보인다.
React Apollo는 cache를 가지고 있다.
만약 React Apollo가 뭔가를 얻으면 그거를 저장해 둔다.

data를 바로 사용하면 error

const {loading, data} = useQuery(GET_MOVIE, {
        variables: {id: parseInt(id)},
    });
    return (
        <Container>
            <Column>
   >>>>        <Title>{data.movie.title}</Title>
      ```
위의 부분은
` <Title>{loading? "Loading...": data.movie.title}</Title>`
이렇게 작성해야한다.

### Optional Chaining
` bg={data && data.movie ? data.movie.medium_cover_image : ""}`
이것을 Optional Chaining을 사용해서 바꾸면
`bg={data?.movie?.medium_cover_image}`


### Local State
만약 local state를 바꾸고 싶다면 client에 mutation을 생성해서 바꿀 수 있다.

Apollo에게 mutation이 @client에 있다고 알려줘야한다. 
```js
const LIKE_MOVIE = gql`
  mutation likeMovie($id: Int!) {
    likeMovie(id: Id) @client
  }
`;

데이터를 write하기 위해 cache 사용

apollo.js

    Mutation: {
      likeMovie: (_, { id }, { cache }) => {
        cache.writeData({
          id: `Movie:${id}`,
          data: {
            isLiked: true,
          },
        });
      },
    },

로컬 환경에서 data를 바꾸는 것에서 중요한점!

새로운 필드를 movie resolver에서 생성했다는 것
이것은 API랑 같은 이름이어야한다.
그 다음에 mutation을 만들었다.

apollo.js

const client = new ApolloClient({
  uri: "http://localhost:4000",
  resolvers: {
    Movie: {
      isLiked: () => false,
    },

like 버튼 누르기전 isLiked는 false

like 버튼 누르면 isLiked는 true

0개의 댓글

관련 채용 정보