GraphQLとReactを使用したムービーWebの作成

26120 ワード

Apollo


:ApolloはGraphQL APIを使用する良い方法です.
REST APIはURLでJSONを受信します.
GraphQLはqueryまたは変異を送信する必要があります.
設定
npxcreate−react−appApollomovienpx create-react-app Apollo_movienpxcreate−react−appApollom​ovieyarn add styled-components react-router-dom apollo-boost @apollo/react-hooks graphql

ルーティングの設定


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のように、すべてが設定されたパッケージです.
GraphQL Yogaは直接使用できるサーバを用意していますが、apollo-boostはクライアントです.
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


userQueryを使用したデータのインポート


fetchやJSONなどの操作を行わずにuseQueryを使用してデータをインポートできます.
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にidなどの変数がある場合は、そのqueryの名前を記入する必要があります.
(Apollo、React、GraphQL、React Apollo用)
queryの名前の部分はApolloのために書かれています.Apolloが変数のタイプをチェックするのを助けます.
ここで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をもう一度押すと、loadは表示されずにタイトルが表示されます.
react Apolloにはcacheがあります.
react Apolloが何かを手に入れたらそれを保存します

直ちにdataを使用中にエラーが発生しました

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
  }
`;

cacheを使用してデータを書き込む


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

ローカル環境でデータを変更することが重要です。


movie解析器に新しいフィールドが作成されました
これはAPIと同名のはずです.
そして突然変異を起こしました
apollo.js
const client = new ApolloClient({
  uri: "http://localhost:4000",
  resolvers: {
    Movie: {
      isLiked: () => false,
    },
likeボタンを押す前にisLikedがfalseになります

likeボタンisLikedをtrueとする