下記記事の続きです。
前回はデータを取得して画面に表示するところまでだったので、今回はデータを更新できるようにします。
*参考
*環境
- MacOS
- react 16.9.0
- graphql 14.4.2
- react-apollo 3.0.0
- react-router 5.0.1
- react-router-dom 5.0.1
*データの更新
CreateLink
コンポーネントを新規作成します。画面から入力される値は
state
で管理し、setState()
で更新します。<Mutation />
を使ってデータ更新の API リクエストを行います。プロパティではmutation
に実行したいクエリ、variables
に更新する値を渡します。<button />
を<Mutation />
で囲むことで、ボタンをクリックするとリクエストが実行されるようになります。<react-app/src/components/CreateLink.js>
import React, { Component } from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";
// ---- gqlでGraphQLのクエリを作成 ----
const POST_MUTATION = gql`
mutation PostMutation($description: String!, $url: String!) {
post(description: $description, url: $url) {
id
createdAt
url
description
}
}
`;
class CreateLink extends Component {
state = {
description: "",
url: ""
};
render() {
const { description, url } = this.state;
return (
<div>
<div className="flex flex-column mt3">
<input
className="mb2"
value={description}
onChange={e => this.setState({ description: e.target.value })}
type="text"
placeholder="A description for the link"
/>
<input
className="mb2"
value={url}
onChange={e => this.setState({ url: e.target.value })}
type="text"
placeholder="The URL for the link"
/>
</div>
// ---- 更新リクエスト -----
<Mutation mutation={POST_MUTATION} variables={{ description, url }}>
{postMutation => <button onClick={postMutation}>Submit</button>}
</Mutation>
</div>
);
}
}
export default CreateLink;
初期表示の画面で
CreateLink
を表示するようApp.js
を修正します。<react-app/src/components/App.js>
import React, { Component } from "react";
// ---- ↓修正 ----
import CreateLink from "./CreateLink";
class App extends Component {
render() {
// ---- ↓修正 ----
return <CreateLink />;
}
}
export default App;
サーバーをそれぞれ起動します。
## Reactアプリ側
/react-app/
$ npm start
## サーバー側
/react-app/server
$ npm start
下記リンクにアクセスすると、リンク先の説明とURLを入力する画面が表示されます。
http://localhost:3000/
The best learning resource for GraphQL
www.howtographql.com
Playground で下記を実行してデータを取得すると、更新されていることが確認できます。
query GetLink{
feed {
links {
id
description
url
createdAt
}
}
}
<実行結果>
{
"data": {
"feed": {
"links": [
...
{
"id": "cjz96btz68n1b0b53mgc0en37",
"description": "The best learning resource for GraphQL",
"url": "www.howtographql.com",
"createdAt": "2019-08-13T01:55:24.930Z"
}
]
}
}
}
<Playground>
*ルーティングの実装
新規作成画面と更新画面にそれぞれアクセスできるよう、ヘッダーを作成します。Apollo でルーティング機能を実装するためには
react-router
が必要なのでインストールします。$ npm install react-router react-router-dom --save
Header
コンポーネントを新規作成します。<react-app/src/components/Header.js>
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { withRouter } from "react-router";
class Header extends Component {
render() {
return (
<div className="flex pal justify-between npwrap orange">
<div className="flex flex-fixed black">
<div className="fw7 mr1">Hacker News</div>
<Link to="/" className="ml1 no-underline black">
new
</Link>
<div className="ml1">|</div>
<Link to="/create" className="ml1 no-underline black">
submit
</Link>
</div>
</div>
);
}
}
export default withRouter(Header);
初期表示の画面でヘッダーを表示させるよう
App.js
を修正します。<Route />
のpath
で対応させたいURL、component
に描画したいコンポーネントを指定します。exact
を指定するとpath
が完全一致したときのみマッチしたことになります。(指定しないと前方一致した全てに適用されてしまいます)そして
<Switch />
で<Route />
をグループ化します。<react-app/src/components/App.js>
import React, { Component } from "react";
import CreateLink from "./CreateLink";
import LinkList from "./LinkList";
// ---- ↓追加 ----
import Header from "./Header";
import { Switch, Route } from "react-router-dom";
class App extends Component {
render() {
return (
// ---- ↓修正 ----
<div className="center w85">
<Header />
<div className="ph3 pv1 background-gray">
<Switch>
<Route exact path="/" component={LinkList} />
<Route exact path="/create" component={CreateLink} />
</Switch>
</div>
</div>
);
}
}
export default App;
データ登録後、最初の画面に自動で遷移するよう修正します。
<Mutation>
にonCompleted
を追加します。onCompleted
は更新が正常完了したときに実行される処理です。<react-app/src/components/CreateLink.js>
import React, { Component } from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";
const POST_MUTATION = gql`
mutation PostMutation($description: String!, $url: String!) {
post(description: $description, url: $url) {
id
createdAt
url
description
}
}
`;
class CreateLink extends Component {
state = {
description: "",
url: ""
};
render() {
const { description, url } = this.state;
return (
<div>
<div className="flex flex-column mt3">
<input
className="mb2"
value={description}
onChange={e => this.setState({ description: e.target.value })}
type="text"
placeholder="A description for the link"
/>
<input
className="mb2"
value={url}
onChange={e => this.setState({ url: e.target.value })}
type="text"
placeholder="The URL for the link"
/>
</div>
// ---- ↓onCompletedを追加 ----
<Mutation
mutation={POST_MUTATION}
variables={{ description, url }}
onCompleted={() => this.props.history.push("/")}
>
{postMutation => <button onClick={postMutation}>Submit</button>}
</Mutation>
</div>
);
}
}
export default CreateLink;
アプリケーションを起動するとヘッダーが追加され、新規登録と更新ができるようになっています。
<初期表示>
<新規登録>
<更新>
*所感
更新の実装をするのも非常に簡単でした。簡単であるがゆえに、内部ではどう動いているのか、どういった部分に使うべきなのかといった考慮が必要かと感じました。このチュートリアルでは Apollo を使った実装方法を学ぶと同時に React についても勉強になりました。まだ認証などの続きがあるので時間のあるときに取り組みたいと思います。
Sign up here with your email
1 コメント:
Write コメントThank you for the comment.
ReplyI'm glad to say that. I will study and post more.
ConversionConversion EmoticonEmoticon