前回に続いて
前回までの記事でApolloServer配下でGraphQLが動作し、GraphQL APIというか、GraphQL クエリ言語で、商品テーブルのデータ登録、読み込みができるようになったので、今回はフロントエンドをReact+Reduxで組み始めるところを説明します。Reactはそれほどでもないのですが、Reduxのことをわかっていないとナンノコッチャよく分からんということになると思いますので、各自Reduxの予習はみっちりしてください。
この記事は5回に分けて連載する、第3回の記事です。
・第1回 Apollo Serverが動くところまで
・第2回 Apollo Server配下で、GraphQLを使って商品マスターにアクセスする
・第3回 フロントエンドをReact+Redux+graphql-requestを使って実装する(この記事)
・第4回 フロントエンドからgraphql-requestを使って、データを取得・表示する
・第5回 graphql-requestを使って、データを登録・修正・削除する
完成形のファイルツリー
説明が下手で、どこのファイルをいじっているのかわかりにくくなると思うので、完成形のファイルツリーを表示しておきます。

フロントエンドプロジェクトの作成
create-react-app を使って、プロジェクトを作ります。
[bash]
$ cd ~/workspace/graphql-master
$ sudo npm install -g create-react-app
$ create-react-app front
[/bash]
npm を使って必要なモジュールインストール
[bash]
$ cd front
$ npm start
$ npm install –save react-router-dom redux react-redux graphql-request
[/bash]
Reduxに必要なフォルダ構成を作成
[bash]
$ mkdir src/actions
$ mkdir src/components
$ mkdir src/constants
$ mkdir src/containers
$ mkdir src/reducers
$ mkdir src/sass
[/bash]
アプリケーションファイル App.jsを再定義
自動生成されたApp.jsを以下のように、ごっそり書き換えてください。
ルーティングにはreact-router-domを使い、
Home/About/Product(商品マスタ) の3画面構成にします。
[bash]
$ nano App.js
[/bash]
[bash]
import React from ‘react’;
import {Router, Route} from “react-router-dom”;
import history from ‘./history’;
import Home from “./components/home”;
import About from “./components/about”;
import Product from “./components/product”;
function App() {
return (
GraphQL と Apollo Serverを使ったマスターメンテナンス
);
}
export default App;
[/bash]
App.jsに記述した諸々を定義
react-routerのヒストリーを管理するファイルです。
[bash]
$ nano history.js
[/bash]
[bash]
import { createBrowserHistory as createHistory } from ‘history’
export default createHistory()
[/bash]
3画面共通のメニュー定義です。
[bash]
$ nano components/menu.js
[/bash]
[bash]
import React from “react”
import {Link} from “react-router-dom”;
class Menu extends React.Component {
render() {
return (
)
}
}
export default Menu;
[/bash]
ホーム画面
[bash]
$ nano componetns/home.js
[/bash]
[bash]
import React from “react”;
import Menu from “./menu”;
class Home extends React.Component {
render(){
return (
This is Home
)
}
}
export default Home;
[/bash]
About画面
[bash]
$ nano componetns/about.js
[/bash]
[bash]
import React from “react”;
import Menu from “./menu”;
class About extends React.Component {
render(){
return (
This is About
)
}
}
export default About;
[/bash]
Product画面(商品マスターのメイン画面)
[bash]
$ nano componetns/product.js
[/bash]
[bash]
import React from “react”;
import Menu from “./menu”;
class Product extends React.Component {
render(){
return (
This is Product
)
}
}
export default Product;
[/bash]
ここまでを動作確認
こんな感じに表示されれば、成功です。


Reduxのreducerを定義
ここからは reduxの基礎知識がある前提で書き進めます。
ツライと思いますが、写経してください。
[bash]
$ nano reducers/root.js
[/bash]
[bash]
import {combineReducers} from “redux”;
import product from “./Product/product”;
const rootReducer = combineReducers({
product: product,
})
export default rootReducer;
[/bash]
[bash]
$ mkdir reducers/Product
$ nano reducers/Product/product.js
[/bash]
[bash]
import {combineReducers} from “redux”
import list_body from “./list_body”;
import mode from “./mode”;
import product_info from “./product_info”;
const product = combineReducers({
list_body: list_body,
mode: mode,
product_info: product_info,
})
export default product;
[/bash]
[bash]
$ nano reducers/Product/list_body.js
[/bash]
[bash]
import {PRODUCT_SET_LIST_BODY} from “../../constants/index”
const list_body = (state=[], action) => {
switch (action.type) {
case PRODUCT_SET_LIST_BODY:
let newState = [];
for (let i = 0 ; i < action.list_body.length; i++){
let copy = Object.assign({}, action.list_body[i]);
newState.push(copy);
}
return newState
default:
return state
}
}
export default list_body
[/bash]
[bash]
$ nano reducers/Product/mode.js
[/bash]
[bash]
import {PRODUCT_SET_MODE} from "../../constants/index"
const mode = (state="ADD", action) => {
switch (action.type) {
case PRODUCT_SET_MODE:
return action.mode
default:
return state
}
}
export default mode
[/bash]
[bash]
$ nano reducers/Product/product_info.js
[/bash]
[bash]
import {PRODUCT_SET_PRODUCT_INFO} from “../../constants/index”
const product_info = (state=null, action) => {
switch (action.type) {
case PRODUCT_SET_PRODUCT_INFO:
let copy = Object.assign({}, action.product_info)
return copy
default:
return state
}
}
export default product_info
[/bash]
[bash]
$ nano reducers/Product/has_more.js
[/bash]
[bash]
import {PRODUCT_SET_HAS_MORE} from “../../constants/index”
const has_more = (state=false, action) => {
switch (action.type) {
case PRODUCT_SET_HAS_MORE:
return action.has_more
default:
return state
}
}
export default has_more
[/bash]
Redux reducerで使った定数を定義
定数を定義します。
[bash]
$ nano constants/index.js
[/bash]
[bash]
export const PRODUCT_SET_LIST_BODY = “PRODUCT_SET_LIST_BODY”;
export const PRODUCT_SET_MODE = “PRODUCT_SET_MODE”;
export const PRODUCT_SET_PRODUCT_INFO = “PRODUCT_SET_PRODUCT_INFO”;
export const PRODUCT_SET_HAS_MORE = “PRODUCT_SET_HAS_MORE”;
[/bash]
Reduxのアクションを定義
アクションを定義します。
[bash]
$ nano actions/product.js
[/bash]
[bash]
import {
PRODUCT_SET_LIST_BODY,
PRODUCT_SET_MODE,
PRODUCT_SET_PRODUCT_INFO,
PRODUCT_SET_HAS_MORE,
} from “../constants/index”
export const set_list_body = (list_body) => {
return {
type: PRODUCT_SET_LIST_BODY,
list_body: list_body,
}
}
export const set_mode = (mode) => {
return {
type: PRODUCT_SET_MODE,
mode: mode,
}
}
export const set_product_info = (product_info) => {
return {
type: PRODUCT_SET_PRODUCT_INFO,
product_info: product_info,
}
}
export const set_has_more = (has_more) => {
return {
type: PRODUCT_SET_HAS_MORE,
has_more: has_more,
}
}
[/bash]
index.jsのRedux対応
index.js を redux 対応させます。
[bash]
import React from ‘react’;
import ReactDOM from ‘react-dom’;
import ‘./index.css’;
import App from ‘./App’;
import * as serviceWorker from ‘./serviceWorker’;
import {Provider} from “react-redux”;
import {createStore} from “redux”;
import rootReducer from “./reducers/root”
let store = createStore(rootReducer, /* preloadedState, */
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
ReactDOM.render(
,
document.getElementById(‘root’));
[/bash]
つまらない作業でしたね。お疲れさまでした。
とりあえず、今回はここまでで、次回はいよいよ、graphql-requestを使って、Apollo ServerへGraphQL言語でアクセスして、データを取得したり、更新したりしてみましょう!
Leave a comment