React + Apollo Client -Mutation ユーザー認証編-
このセクションではApollo Client + React でのMutationの使い方をユーザー認証と共に学習します。
Register.jsの実装
src/Register.jsを作成します。同時にルーティングの使用したいのでreact-router-domreact-routerをインストールします。
npm i react-router-dom react-router
pagesデイレクトリをつくりその中にLogin.jsRegister.jsTodoListing.jsを作成します。またgraphqlディレクトリにQueryやMutationを記述します。
src下はこのようになっています。トップページ(ここではhttp://localhost:3000)にTodoListing.jsを持ってきてTodoを表示します。
├── graphql
├── index.js
├── App.js
├── pages
├── Login.js
├── Register.js
├── TodoListing.js
//src/App.js
import { BrowserRouter as Router, Route, Switch} from 'react-router-dom'
import Register from './pages/Register';
import Login from './pages/Login';
import TodoListing from './pages/TodoListing';
function App() {
return (
<Router>
<Switch>
<Route path="/register" component={Register} />
<Route path="/login" component={Login} />
<Route path="/" exact component={TodoListing} />
</Switch>
</Router>
);
}
export default App;
上のようにApp.jsでルーティングをおこなっています。
先にMutationを扱う前にユーザー登録のためのフォームをpages/Register.jsからかいていきます。
// src/pages/Register.js
import React, { useState } from 'react'
function Register() {
const [ username, setUsername ] = useState("")
const [ email, setEmail ] = useState("")
const [ password, setPassword ] = useState("")
const onSubmit = (e) => {
e.preventDefault();
}
return (
<form onSubmit={onSubmit}>
<input type="text" placeholder="username" onChange={(e) => setUsername(e.target.value)} value={username} />
<input type="email" placeholder="email" onChange={(e) => setEmail(e.target.value)} value={email} />
<input type="password" placeholder="password" onChange={(e) => setPassword(e.target.value)} value={password} />
<button type="submit">register</button>
</form>
)
}
export default Register
Reactをかいている人にとっては定番だと思うのでここでのuseStateやonClickの説明は省略します。ここではユーザーが書いたフォームがGraphQLの引数のargsの部分として送信されます。Queryのときと同様にuseMutationというReact Hookのひとつを使います。
graphqlディレクトリ下にqueriesとmutationsディレクトリを作成しまずmutations下にregister.jsファイルを作成します。
// src/graphql/mutations/register.js
import { gql } from "@apollo/client";
export const USER_REGISTER = gql `
mutation registerMutation($username: String!, $email: String!, $password: String!){
register(username: $username, email: $email, password: $password){
username
email
}
}`
まず前回と同様にgqlを使用してmutationを書いていきます。またここでは厳密に型付けとnull-ableな関数であるかを指定する必要があります。
先ほどユーザー登録フォームを記述したpages/Register.jsにRegister(ユーザー登録)のMutationを実装していきます。
// pages/Register.js
import React, { useState } from 'react'
import { useMutation, gql } from '@apollo/client';
import { useHistory } from 'react-router';
import { USER_REGISTER } from '../graphql/mutations/register';
function Register() {
const history = useHistory();
const [ username, setUsername ] = useState("")
const [ email, setEmail ] = useState("")
const [ password, setPassword ] = useState("")
const onSubmit = (e) => {
e.preventDefault();
register()
}
const [register] = useMutation(USER_REGISTER, {
variables: {
username,
email,
password
},
onCompleted: () => history.push('/login')
})
return (
<form onSubmit={onSubmit}>
<input type="text" onChange={(e) => setUsername(e.target.value)} value={username} />
<input type="email" onChange={(e) => setEmail(e.target.value)} value={email} />
<input type="password" onChange={(e) => setPassword(e.target.value)} value={password} />
<button type="submit">register</button>
</form>
)
}
export default Register
src/graphql/mutations/register.jsに作成したUSER_REGISTERをuseMutationに渡します。同時にユーザーがフォームで書いたユーザーネームなどのvariables(変数)もわたす必要があります。onCompletedはmutationが完了した後に実行する関数でここではユーザー登録後にログインを行いたいのでonCompleted: () => history.push('/login')としました。最後にonSubmitにregister()を渡せば完了です。
npm startでhttp://localhost:3000/registerにいって新たにユーザーを作成してみてください。無事に完了すれば/loginにとびます。
Login.jsの実装
Login.jsもRegister.js同様に src/pages下に作成していきます。そしてログインのMutationをsrc/graphql/mutations/login.jsを作成し、register同様に
// src/graphql/mutations/login.js
import { gql } from "@apollo/client";
export const USER_LOGIN = gql `
mutation loginMutation($email: String!, $password: String!){
login(email: $email, password: $password){
username
email
}
}`
// src/pages/Login.js
import React, { useState } from 'react'
import { useMutation, gql } from '@apollo/client';
import { useHistory } from 'react-router';
import { USER_LOGIN } from '../graphql/mutations/login';
function Login() {
const history = useHistory();
const [ email, setEmail ] = useState("")
const [ password, setPassword ] = useState("")
const onSubmit = (e) => {
e.preventDefault();
login()
}
const [login] = useMutation(USER_LOGIN, {
variables: {
email,
password
},
onCompleted: () => history.push('/')
})
return (
<form onSubmit={onSubmit}>
<input type="email" onChange={(e) => setEmail(e.target.value)} value={email} />
<input type="password" onChange={(e) => setPassword(e.target.value)} value={password} />
<button type="submit">login</button>
</form>
)
}
export default Login
Registerのときとほとんど同じコードですが今回は完了したらhttp://localhost:3000のトップページにかえってくるようにします。
最後にログインしているユーザーをregister.jsやlogin.jsにきたときにトップページに返すようにコードを加えます。ここではバックエンド編で実装したmeQueryというログインしているユーザー情報を取り出すQueryを使います。
まずはgraphql/queries下にme.jsというファイルを作成し、以下のQueryを記述します。
// src/graphql/queries/me.js
import { gql } from "@apollo/client";
export const ME_QUERY = gql `
query Me {
me {
id
username
email
}
}
}`
register.jsやlogin.jsに以下のコードをたします。ページにアクセスしたときにログインしているかどうかを確かめています。
iport { ME_QUERY } from '../graphql/queries/me';
.....
const { loading, data } = useQuery(ME_QUERY)
useEffect(() => {
if(!loading && data.me){
history.push('/')
}
},[loading, data, history])
足早に実装したので一度src/pages/Register.jsとsrc/pages/Login.jsを確認して自分のコードと照らし合わせてみてください。
ここでユーザー認証のユーザー登録とログインをパートを終了します。次からはTodoのCRUDのCREATE、UPDATE、DELETEを実装します。