kintone-React自習 8日目「React-kintone連携チュートリアル の作成」入力フォームにkintoneのレコードを表示する
自習 6日目で作成した入力フォームにkintoneのレコードを取得して表示する。
3. 入力フォームにkintoneのレコードを表示する
kintone-Reactの開発環境を設定する
kintone-Reactの開発環境は、Goqoo on kintoneを利用します。
下記を参照。
流れだけ以下にまとめ。
適当なディレクトリで `npx goqoo new プロジェクト名` する。
プロジェクト名ディレクトリに `cd` する。
`git commit -m "Initial commit"` する。
`npx goqoo generate app customview` する。
React, React-DOM モジュールをインストールする。(*追加のnpmモジュールリスト参照)
kintone-rest-api-client モジュールをインストールする。(*追加のnpmモジュールリスト参照)
goqoo.config.types.ts 編集。AppIdの設定。
goqoo.config.js 編集。bundlerType: 'react'。environments:にアプリID等設定。
.env ファイルにkintoneの認証情報を追加。
`npx goqoo generate dts` する。
7.~10.は下記も参照。
*追加のnpmモジュールリスト
package.jsonに書いて、`npm install`する。
"devDependencies": {
"@kintone/rest-api-client": "^2.0.33",
"@types/bootstrap": "^5.1.0",
"@types/react": "^17.0.15",
"@types/react-dom": "^17.0.9",
・・・
"dependencies": {
"bootstrap": "^5.1.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
・・・
App.tsx他の作成
前段で作成したReactのフォームをコピーします。
kintoneのカスタマイズビューで表示されるように一部修正します。
App.tsx
import "./styles.css";
import React, { useState, useRef } from "react";
import * as ReactDOM from 'react-dom'
import type { IndexEvent } from 'types'
export default function App() {
const [searchString, setSearchString] = useState("");
const [numberOfDeliveryNote, setNumberOfDeliveryNote] = useState("");
const [itemName, setItemName] = useState("");
const [statusOfDelivery, setStatusOfDelivery] = useState("未納品");
const [orderingQuantity, setOrderingQuantity] = useState(0);
const [deliveryDate, setDeliveryDate] = useState("2022-01-01");
const [deliveryQuantity, setDeliveryQuantity] = useState(0);
const [isSearch, setIsSearch] = useState(false);
const deliveryQuantityInput = useRef<HTMLInputElement>(null);
const numberOfDeliveryInput = useRef<HTMLInputElement>(null);
const confiremButton = useRef<HTMLButtonElement>(null);
const fetchRecord = (number_of_delivery_note: string) => {
const record = {
number_of_delivery_note: "12345991",
status_of_delivery: "納品済",
item_name: "BA-2343",
ordering_quantity: 24,
item_number: "77788",
ordering_date: "2022-01-10",
delivery_quantity: 25,
delivery_date: "2022-02-01",
order_backlog: 0
};
return record;
};
const handleSubmit = (event: any) => {
console.log(event); // eslint-disable-line no-console
event.preventDefault();
confiremButton.current?.focus();
setIsSearch(true);
const record = fetchRecord(searchString);
setTimeout(() => {
const {
number_of_delivery_note,
item_name,
status_of_delivery,
ordering_quantity,
delivery_quantity,
delivery_date
} = record;
setNumberOfDeliveryNote(number_of_delivery_note);
setItemName(item_name);
setStatusOfDelivery(status_of_delivery);
setOrderingQuantity(ordering_quantity);
setDeliveryQuantity(delivery_quantity);
setDeliveryDate(delivery_date);
setIsSearch(false);
setSearchString("");
}, 5000);
};
const handleClick = (event: any) => {
console.log(event); // eslint-disable-line no-console
event.preventDefault();
if (event.target.value === "confirmation") {
console.log(event.target.value); // eslint-disable-line no-console
alert("保存しました");
numberOfDeliveryInput.current?.focus();
}
};
return (
<div className="App">
<h1>検収処理</h1>
<h2>{isSearch ? "Start searching..." : ""}</h2>
<div>
<form onSubmit={handleSubmit}>
<span>納品書番号入力:</span>
<input
type="text"
name="search"
value={searchString}
ref={numberOfDeliveryInput}
autoFocus={false}
onChange={(event) => setSearchString(event.target.value)}
/>
<button type="submit" name="search" value="search">
検索
</button>
<div>
<span>納品書番号:</span>
<input type="label" defaultValue={numberOfDeliveryNote} />
</div>
<div>
<label htmlFor="deliveryQuantity">納品数</label>
<input
name="number"
type="number"
ref={deliveryQuantityInput}
value={deliveryQuantity}
onChange={(event: any) => setDeliveryQuantity(event.target.value)}
/>
<button
type="button"
name="confirmation"
value="confirmation"
ref={confiremButton}
onClick={handleClick}
>
検収確認
</button>
</div>
</form>
<div>納品書番号:{numberOfDeliveryNote}</div>
<div>ステータス:{statusOfDelivery}</div>
<div>品名:{itemName}</div>
<div>発注数:{orderingQuantity}</div>
<div>納品日:{deliveryDate}</div>
</div>
</div>
);
}
kintone.events.on('app.record.index.show', async (event: IndexEvent<kintone.types.SavedDeliveryNoteFields>) => {
const container = document.getElementById('react-sample-container')
if (!container) {
return event
}
ReactDOM.render(<App />, container);
return event
})
styles.css
.App {
font-family: sans-serif;
text-align: center;
}
index.ts
import { goqoo } from 'goqoo'
goqoo('app', () => {
require('./App')
})
kintoneのカスタマイズビューの設定
HTMLにReactをレンダリングするターゲットのid属性を設定。
<div id="react-sample-container"></div>

kintoneからレコード取得
kintone-rest-api-clientモジュールを利用して、フォームに入力された条件からクエリでレコードをフェッチします。
import { KintoneRestAPIClient } from "@kintone/rest-api-client"
・・・
// kintoneからレコードを取得する
const fetchRecord: any = (number_of_delivery_note: string) => {
const client = new KintoneRestAPIClient();
const APP_ID = context.appId.delivery_note;
const params = {
app: APP_ID,
fields: ["number_of_delivery_note", "status_of_delivery",
"item_name", "ordering_quantity", "item_number", "ordering_date",
"delivery_quantity", "delivery_date", "order_backlog",
],
query: `number_of_delivery_note = ${number_of_delivery_note} order by レコード番号 asc limit 1`
};
return new Promise ((resolve, reject) => {
client.record.getRecords(params).then((response) => {
console.log(response); // eslint-disable-line no-console
return resolve(response.records[0]);
}).catch((err) => {
console.log(err.id); // eslint-disable-line no-console
console.log(err.code); // eslint-disable-line no-console
console.log(err.headers); // eslint-disable-line no-console
console.log(err.message); // eslint-disable-line no-console
return reject(err);
});
});
};
ここまでの、App.tsxは下記になります。
https://gist.github.com/sy250/a2b2260c9477bb11b8b1d221a8ba7ed4
参考:
開発フレームワーク「Goqoo on kintone」を正式リリースしました!
https://qiita.com/the_red/items/3222d8bf71c32d769060