ApolloでReactからGraphQLのQueryとMutationしてみる
概要
SpringBootとGraphQLで素敵なAPI作成の記事で作った2本のGraphQL APIをReactから呼び出すのにApolloを使ってみる。
Introduction | Apollo ClientにあるEssentialのQuery, Mutationレベルで作ってみる。
もういろいろ書くの面倒になってきたんでこの辺のソースとってきて
npm startってたたいてhttp://localhost:3000/search_memberにブラウザでアクセスしてみてくださいな
Apollo関連をインストール
必要なものをnpmでインストール
npm install apollo-boost react-apollo graphql --save
Queryを実行
名前入力して検索ボタンで検索できるようにしてみる
まずはQueryで呼び出す
基本この書き方が型っぽい。
dataにGraphQLAPIから返ってきた情報が入ってるのでそれをMemberTableコンポーネントに渡してぐるぐる回して表示
/src/containers/MemberTable.jsx
import React from "react";
import gql from "graphql-tag";
import { Query } from "react-apollo";
import MemberTable from "../components/MemberTable";
const GET_MEMBERS_BY_NAME = gql`
query Members($name: String!) {
members(name: $name) {
members {
id
name
createdAt
updatedAt
}
errors {
code
message
}
}
}
`;
const SearchMember = ({ ...props }) => (
<Query query={GET_MEMBERS_BY_NAME} variables={{ name: props.name }} >
{({ loading, error, data }) => {
if (loading) return "Loading...";
if (error) return `Error! ${error.message}`;
return (
<MemberTable data={data} />
);
}}
</Query>
);
export default SearchMember;
検索クリックしたときに検索するにする
Queries | Apollo Clientによるとクリック時にquery実装すると<Query>じゃなくてqlient.query()で冗長的になるから、表示したタイミングで実行するのが適切なのかも。
とはいえ初志貫徹で検索ボタン押したら検索できるようにしてみる。
本当はapollo-link-stateを使いたいところですが、今回はstateで簡易的に実現。
- 入力項目に変更が入ったらstateに保存
- 検索ボタンクリックで入力項目のstateを検索用のstateに保存
- 検索用のstateを上で作ったQueryのvariablesに渡してるって寸法
/src/views/SearchMember/SearchMember.jsx
import React from "react";
import SearchByNameBar from "../../components/SearchByNameBar";
import MemberTable from "../../containers/MemberTable";
class SearchMember extends React.Component {
constructor() {
super();
this.state = {
input: {
name: ""
},
search: {
name: ""
}
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleClickSearch = this.handleClickSearch.bind(this);
}
handleInputChange(event) {
this.setState({
input: {
name: event.target.value
}
});
}
handleClickSearch(event) {
event.preventDefault();
this.setState({
search: {
name: this.state.input.name
}
});
}
render() {
return (
<div>
<p><b>SearchMember</b></p>
<SearchByNameBar handleInputChange={this.handleInputChange} handleClickSearch={this.handleClickSearch} />
<MemberTable data={this.props.data} name={this.state.search.name} />
</div>
)
}
}
export default SearchMember;
Mutationを実行
基本的な方はこんな感じ。
apollo-link-stateをうまく使えば、Mutation実行とともにローカルのデータが更新されて、別コンポーネントのデータを更新とかもできるはず。。。
とりあえず1つのコンポーネントで完結するように書いてみる
/src/components/RegistNameBar.jsx
import React from "react";
import gql from "graphql-tag";
import { Mutation } from "react-apollo";
const ADD_MEMBER = gql`
mutation ReginstMember($name: String!){
registMember(name: $name) {
registMember {
id
name
}
errors {
code
message
}
}
}
`;
function RegistNameBar({ ...props }) {
let input;
return (
<Mutation mutation={ADD_MEMBER}>
{(addMember, { loading, error, data }) => (
<div>
<form
onSubmit={e => {
e.preventDefault();
addMember({ variables: { name: input.value } });
input.value = "";
}}
>
<div>
Name <input type="text" ref={node => { input = node; }} /> <input type="submit" value="Regist" />
</div>
</form>
{data && <p>Regist Success!!</p>}
{loading && <p>Loading...</p>}
{error && <p>Error :( Please try again</p>}
</div>
)}
</Mutation>
);
}
export default RegistNameBar;
まとめ
Apolloはリモートとローカルの情報を同期させたり、認証もよろしくできたり、可視化のEngineがあったり可能性は感じるけど、ちゃんと勉強しないと使いこなせなさそう。。。
通勤時間に調べて次のアプリ作成では入れてやろうと思う。