Apollo Server、GraphQL、nodejs、sequesize、フロントにReact+Reduxで マスターメンテナンスを作ろう! 〜Vol.5

Apollo Server、GraphQL、nodejs、sequesize、フロントにReact+Reduxで マスターメンテナンスを作ろう! 〜Vol.5

Apollo Server、GraphQL、nodejs、sequesize、フロントにReact+Reduxで マスターメンテナンスを作ろう! 〜Vol.5

Apollo Server、GraphQL、nodejs、sequesize、フロントにReact+Reduxで マスターメンテナンスを作ろう! 〜Vol.5 へのコメントはまだありません

前回に引き続き

前回までで、データ一覧を表示するところはできました。
今回は最終仕上げ、一覧から編集ボタンを押し、データの編集画面に移動し、データの修正・削除。
一覧から、新規データ作成ボタンを押し、データの新規作成。

細かく説明すると非常に時間がかかるので、ソースコードを貼り付けるのをメインにします。

この記事は5回に分けて連載する、第5回の記事です。

・第1回 Apollo Serverが動くところまで

・第2回 Apollo Server配下で、GraphQLを使って商品マスターにアクセスする

・第3回 フロントエンドをReact+Redux+graphql-requestを使って実装する

・第4回 フロントエンドからgraphql-requestを使って、データを取得・表示する

・第5回 graphql-requestを使って、データを登録・修正・削除する(この記事)

ファイルツリー

今回も完成形のファイルツリーをまず示しておきます。
Screenshot from 2019-05-13 22-12-07

一覧画面の編集

変更箇所は「新規データ作成」ボタンを追加したところと、Reactが警告を出していたので、
明細業のデータに key を付与したところでしょうか。

[bash]
$ nano components/product.js
[/bash]

[bash]
import React from “react”;
import {withRouter} from “react-router-dom”;
import Menu from “./menu”;

class Product extends React.Component {
componentDidMount() {
this.props.onInit();
}
render(){
let {list_body, has_more, onClickEdit, onAddNew} = this.props;

let lstBody = [];

for (let i = 0 ; i < list_body.length ; i++){ let bd = list_body[i]; lstBody.push(

{bd.id}
{bd.product_name}
{bd.price}

);
}

return (

This is Product

{lstBody}

)
}
}

export default withRouter(Product);
[/bash]

一覧画面に対応するコンテナの編集

onClickEdit,onAddNew でページ遷移させるところが主な変更点。

[bash]
$ nano containers/cproduct.js
[/bash]

[bash]
import {connect} from “react-redux”;
import {GraphQLClient} from “graphql-request”;

import Product from “../components/product”;
import {set_list_body, set_has_more} from “../actions/product”;

const GET_PRODUCTS = `
query GetProducts ($offset: Int!, $limit: Int!){
getProducts(offset: $offset, limit: $limit){
has_more
products {
id
product_name
price
}
}
}
`;

const HOST_ADDR = “http://localhost:4000”;
let LIST_OFFSET = 0;
let LIST_LIMIT = 100;

const mapStateToProps = (state) => {
return {
list_body: state.product.list_body,
has_more: state.product.has_more,
}
}

const mapDispatchToProps = (dispatch) => {
return {
onInit: () => {
LIST_OFFSET = 0;
onLoadData(LIST_OFFSET, [], dispatch)
},
onClickEdit: (id, history) => {
history.push(“/product/edit/” + id);
},
onAddNew: (history) => {
history.push(“/product/add/none”);
},
onLoadMore: (list_body) => {
onLoadData(LIST_OFFSET, list_body, dispatch);
},

}
}

const onLoadData = (offset, list_body, dispatch) => {

const client = createClient();
let variables = {offset: offset , limit: LIST_LIMIT};

client.request(GET_PRODUCTS, variables).then(data => {
let newList = list_body;
for (let i=0; i < data.getProducts.products.length; i++){ newList = newList.concat(data.getProducts.products[i]); } dispatch(set_list_body(newList)); LIST_OFFSET += LIST_LIMIT; dispatch(set_has_more(data.getProducts.has_more)); }) } const createClient =() => {
const client = new GraphQLClient(HOST_ADDR + “/graphql”, {
headers: {
“x-token”: “test-test”,
},
});

return client;
}

const CProduct = connect(mapStateToProps, mapDispatchToProps)(Product)

export default CProduct

[/bash]

データ編集画面

一覧画面から 編集ボタンを押すと飛んでくる データ編集画面を作ります。
この作業と、この画面に対応するコンテナさえ作れば、マスターメンテナンスは完成です。

細かい説明はしません、必死になってソースを追ってみてください。

[bash]
$ nano components/product_main.js
[/bash]

[bash]
import React from “react”;
import {withRouter} from “react-router-dom”;

class ProductMain extends React.Component {
componentDidMount(){
this.props.onInit(this.props.match.params.id);
}
render() {
let {mode, product_info,
onChangeId, onBlurId ,onChangeProductName,
onChangePrice, onRegister} = this.props;

if (product_info == null){
return

}

return (

ID
onChangeId(product_info, ev.target.value)}
onBlur={(ev)=> onBlurId(product_info)}
/>
商品名
onChangeProductName(product_info, ev.target.value)}
/>
価格
onChangePrice(product_info, ev.target.value)}
/>
{(() => {
if (mode === “ADD”) {
return ;
}
else if (mode === “EDIT”) {
return (


);
}
})()}


)
}
}

export default withRouter(ProductMain);

[/bash]

データ編集画面に対応するコンテナを作成

先程作ったデータ編集画面のイベントハンドリングやプロパティなどを制御するコンテナを作成します。
ここで、ページ表示時に受け取ったパラメーターをもとに GraphQLで、データを取得し、表示。
データ編集がおわったら、ボタンクリックで、データの修正・削除・新規登録を行います。

細かい制御を突っ込みだすと、ツッコミどころはありますが、とりあえず、動くのでこれで良しとしましょう。

ソースの説明はしません。じっくり読んでみてください。

[bash]
$ nano containers/cproduct_main.js
[/bash]

[bash]

import {connect} from “react-redux”;
import {GraphQLClient} from “graphql-request”;

import ProductMain from “../components/product_main”;
import {set_mode, set_product_info} from “../actions/product”;

const GET_PRODUCT = `
query GetProduct($id: Int!) {
getProduct(id: $id){
id
product_name
price
}
}
`;

const REGISTER_PRODUCT = `
mutation RegisterProduct ($mode: String!, $id: Int!, $product_name: String!, $price: Int!){
registerProduct(mode: $mode, id: $id, product_name: $product_name, price: $price){
id
product_name
price
}
}
`;

const HOST_ADDR = “http://localhost:4000”;

const mapStateToProps = (state) => {
return {
//login_info: state.login.login_info,
mode: state.product.mode,
product_info: state.product.product_info,
}
}

const mapDispatchToProps = (dispatch) => {
return {
onInit: (id) => {
let info = {id: “”, product_name: “”, price: “”};
dispatch(set_product_info(info));

if (id !== “none”){
onLoadData(id, dispatch)
}
else {
dispatch(set_mode(“ADD”));
}
},
onChangeId: (product_info, val) => {
product_info.id = val;
dispatch(set_product_info(product_info));
},
onChangeProductName: (product_info, val) => {
product_info.product_name = val;
dispatch(set_product_info(product_info));
},
onChangePrice: (product_info, val) => {
product_info.price = val;
dispatch(set_product_info(product_info));
},
onBlurId: (product_info) => {
onLoadData(product_info.id, dispatch);
},
onRegister: (mode, product_info, history) => {
const client = createClient();
if (product_info.id === “”){
product_info.id = “0”;
}
let variables = {mode: mode, id: parseInt(product_info.id),
product_name: product_info.product_name, price: parseInt(product_info.price)};

client.request(REGISTER_PRODUCT, variables).then(data => {
history.push(“/product”);
})
}
}
}

const onLoadData = (id, dispatch) => {
const client = createClient();
let variables = {id: parseInt(id)};

client.request(GET_PRODUCT, variables).then(data => {
dispatch(set_mode(“EDIT”));

let info = {};
info.id = String(data.getProduct.id);
info.product_name = data.getProduct.product_name;
info.price = String(data.getProduct.price);
dispatch(set_product_info(info));
})

}

const createClient =() => {
const client = new GraphQLClient(HOST_ADDR + “/graphql”, {
headers: {
“x-token”: “test-test”,
},
});

return client;
}

const CProductMain = connect(mapStateToProps, mapDispatchToProps)(ProductMain)

export default CProductMain

[/bash]

App.jsを編集し、詳細画面へジャンプできるようにする

[bash]
$ nano ../App.js
[/bash]

CProductMain 関連を追記しています。

[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 CProduct from “./containers/cproduct”;
import CProductMain from “./containers/cproduct_main”;

import “./sass/main.scss”;

function App() {
return (

GraphQL と Apollo Serverを使ったマスターメンテナンス





);
}

export default App;

[/bash]

動作検証

こんな感じで、データの修正・削除、新規登録ができればOKです。
お疲れさまでした!!!!

Screenshot from 2019-05-13 21-47-47

■新規作成
Screenshot from 2019-05-13 21-50-05

Screenshot from 2019-05-13 21-47-59

Screenshot from 2019-05-13 21-50-17

■データ修正・削除

Screenshot from 2019-05-13 21-50-22

Screenshot from 2019-05-13 21-50-25

About the author:

Related Posts

Leave a comment

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

Back to Top