React + Apollo Client -Mutation CRUD編-

 このセクションでは新しくTodoを作成したり編集するための機能をコードで書いていきます。

AddTodo.jsの作成

src/graphql/mutationsaddTodo.jsを作成します。


// src/graphql/mutatios/addTodo.js 

import { gql } from "@apollo/client";

 export const CREATE_TODO = gql `
 mutation createTodoMutation($content: String!){
    createTodo(content: $content){
        id
        content
    }
}`

続いてはTodoを作成するためのページをつくります。src/pages下にAddTodo.jsを新しくつくり以下のようにコードをかいていきます、


// src/pages/AddTodo.js

import React, { useEffect, useState } from 'react'
import { ADD_TODO } from '../graphql/mutations/addTodo'
import { useHistory } from 'react-router';
import { useMutation, useQuery } from '@apollo/client';
import { ME_QUERY } from '../graphql/queries/me';

function AddTodo() {
    const history = useHistory();
    const [ content, setContent ] = useState("")
    const { loading, data } = useQuery(ME_QUERY)
    const [addTodo] = useMutation(ADD_TODO, {
        variables: {
            content
        },
        onCompleted: () => {
            history.push('/')
        }
    })
    const onSubmit = (e) => {
        e.preventDefault();
        addTodo();
    }
    useEffect(() => {
        if(!loading && !data.me){
            history.push('/login')
        }
    },[loading, data, history])
    return (
        <form onSubmit={onSubmit}>
          <input type="text" value={content} onChange={(e) => setContent(e.target.value)} />  
          <button type="submit">ADD TODO</button>
        </form>
    )
}

export default AddTodo
                    

まずは前回ユーザー認証のときに実装したようにuseMutationaddTodo.jsに定義したスキーマを使用し、addTodo関数を実装します。送信が完了すると確認のためトップページへ戻ります。もしくはconsole.log(addTodo)などで確認しても構いません。

さらにログインしていないユーザーをログイン画面へとかえすためにuseEffectを使って上のように実装します。前回のセクションで最後に実装したユーザー確認に似ていると思います。

 

Todoの編集と削除

 

最後にCRUD機能のUPDATEとDELETEを実装して終わります。やり方は今までと変わりません。まずMutationの定義からおこないます。graphql/mutations下に以下のファイルを作成して定義していきます。


// src/graphql/queries/me.js

import { gql } from "@apollo/client";

 export const ME_QUERY = gql `
  query Me {
 me {
   id
   username
   email
 }
}
}`

Todoを表示しているトップページにそれぞれの機能を加えます。


//  src/pages/TodoListing.js

import React, { useState } from 'react'
import { useMutation, useQuery } from '@apollo/client';
import { GET_TODOS } from '../graphql/queries/listingTodo';
import { DELETE_TODO } from '../graphql/mutations/deleteTodo';
import { UPDATE_TODO } from '../graphql/mutations/updateTodo';
import { ME_QUERY } from '../graphql/queries/me';

function TodoListing() {
    const { loading, error, data } = useQuery(GET_TODOS)
    const [ deleteTodo ] = useMutation(DELETE_TODO)
    const [ updateTodo ] = useMutation(UPDATE_TODO)
    const { loading: meLoading, data: meData } = useQuery(ME_QUERY)
    const [ todo, setTodo ] = useState("")
    if( loading | meLoading ){
        return (
            <p>Loading....</p>
        )
    }
    if( error ){
        return (
            <p>Something went wrong!!</p>
        )
    }
    return (
        <div>
         {data.listing.map(({id, content})=> {
             return (
                 <>
                 <div key={id}>
                 <form>
                 <p>{id}</p>
                 <p>{content}</p>
                 { meData.me && (
                <>
                 <div>
                     <label>編集</label>
                     <input type="text" onChange={(e) => setTodo(e.target.value) } />
                     <button onClick={() => {
                     updateTodo({
                         variables: {
                             id: parseInt(id),
                             content: todo
                         }
                     })
                     setTodo("")}
                    }
                    type="submit">アップデート</button>
                 </div>
                 <p>
                 <button onClick={() => {
                    deleteTodo({ 
                        variables: { id: parseInt(id) }
                    })
                 }}>削除</button></p>
                </>
                 )}
                 </form>
                 </div>
                 </>
             )
         })}    
        </div>
    )
}

export default TodoListing
                    

まずここでもログインしているユーザーのみが変更を行えるようにME_QUERYを使っています。

const { loading: meLoading, data: meData } = useQuery(ME_QUERY)

変数dataはすでに使っているのでここではdataをmeDataに変えておきます。下記のコードはmeDataからユーザーデータを得たもののみが表示されます。



 //  src/pages/TodoListing.js

  { meData.me && (
    <>
     <div>
         <label>編集</label>
         <input type="text" onChange={(e) => setTodo(e.target.value) } />
         <button onClick={() => {
         updateTodo({
             variables: {
                 id: parseInt(id),
                 content: todo
             }
         })
         setTodo("")}
        }
        type="submit">アップデート</button>
     </div>
     <p>
     <button onClick={() => {
        deleteTodo({ 
            variables: { id: parseInt(id) }
        })
     }}>削除</button></p>
    </>
  )}
    

updateTodoではidと変更する内容であるcontentを渡しています。deleteTodoでは削除したいTodoのidを渡しています。

上のようにTodoと編集と削除ボタンができたおり無事にデータの更新を行えれば成功です。またログインしたときに得たcookieを削除してみてください。

削除後ページをリフレッシュすると上のようにデータの変更ができなくなっています。

これで基本的なCRUD機能を実装できたので次はcacheについて学習していきます。ここまでのコードはしたに置いておくので確認してみてください。