Webアプリの勉強に家計簿を作ってみる
モチベーション
社会人になって出費が増えたのでちゃんと管理しようと思って
データベースの勉強も兼ねて家計簿アプリを製作します.
あとはMarkdownの練習.
開発環境
開発環境は下記の通り.
PC : Mac OS 10.14
Node : 12.12.0
npm : 6.13.1
Framework : React & Express
Mysql : 8.0.18
構成
フロントエンドはReactでバックエンドはExpressで開発しています.
サーバーを分ける必要はないと思うんだけど,
複数人数で開発すること考えるとこうした方が勉強になると思って
この図を見るとExpressを介さずにデータベースにアクセスしたした方がよくね,と思っちゃう(体系的に勉強したい,,,)
フロント側
UIについて
React Bootstrapのコンポーネントを利用しています.
Material UIも使ってみよう.
AddとかEditボタンを押したら表示されるモーダル
UIソースコード
<div> <Navbar bg="dark" variant="dark"> <Navbar.Brand> Receipt App </Navbar.Brand> <ButtonGroup> <Button size="sm" variant="light" onClick={onClickBack}><</Button> <Button size="sm" variant="light" onClick={onClickNext}>></Button> </ButtonGroup> <Navbar.Text> {year}/{month} </Navbar.Text> <Navbar.Collapse className="justify-content-end"> <ButtonGroup> <Button variant="primary" onClick={onClickAdd}>Add</Button> <Button variant="secondary" onClick={onClickRefresh}>Refresh</Button> </ButtonGroup> </Navbar.Collapse> </Navbar> <Modal show={show} onHide={onHide}> <Modal.Header closeButton> <Modal.Title>Edit Menu</Modal.Title> </Modal.Header> <Modal.Body> <Edit element={focusReceipt} onSubmit={onClickSave} onClick={onClickDelete}/> </Modal.Body> </Modal> <ReceiptTable onClick={onClickEdit} header={receiptHeader} list={receiptList.filter((e) => {return e.Month==month})}/> </div>
REST APIの一例
const onRead = (e) => { console.log('Call read'); fetch('http://localhost:3000/api/receipts', { method: 'GET', headers : { "Content-type" : "application/json; charset=utf-8" }, body: JSON.stringify(requsetBody) }) .then(response => response.json()) .then(json => { console.log(json); setReceiptList(json); }) .catch(error => console.error('Error:', error)) }
昔のReactだと ステートの初期化はコンストラクターの中で
this.state={param:0}
ステートの変更は
this.setState({param: 10});
だったけど,最近のステートの初期化は
[param, function] = React.useState(0);
ステートの変更は
function(10);
となっている.
エンド側
コンソールでMysqlを編集するのが苦手なので,
サーバー起動時にデータベースを構築するようにした.
app.listen(3000, () => { console.log('Wake up', 'http://localhost:3000') connection.connect((err, result) => { if (err) { console.log('Fail Connecting database!'); throw err; } console.log('Connected to database!'); console.log(result); }); connection.query('CREATE DATABASE IF NOT EXISTS ??', [DB_NAME], function (err, result) { if (err) { throw err; } console.log('Create'); console.log(result); }); connection.query('USE ??', [DB_NAME], function (err, result) { if (err) { throw err; } console.log('Use'); console.log(result); }); connection.query('CREATE TABLE IF NOT EXISTS ??(\ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, \ Date DATE NOT NULL, \ Year INT UNSIGNED, \ Month INT UNSIGNED, \ Day INT UNSIGNED, \ Content VARCHAR(255) NOT NULL, \ Amount INT UNSIGNED NOT NULL DEFAULT 0, \ Shop VARCHAR(255), \ Category INT UNSIGNED NOT NULL DEFAULT 0, \ Necessity VARCHAR(255), \ Note VARCHAR(255), \ Flow VARCHAR(255) NOT NULL)', [MAIN_TABLE_NAME], function (err, result) { if (err) { throw err; } console.log('Create table'); console.log(result); }); })
app.get('/api/receipts', (req, res) => { console.log('Call get & read'); connection.query('SELECT * FROM ?? WHERE Month = ?', [MAIN_TABLE_NAME, req.body['Month']], function(err, results) { if (err) { throw err; } console.log(results); res.send(results); }); });
webpackを使って複数サーバー間で通信が必要になるので
フロントからのアクセス権をいじっておく
app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "*"); res.header("Access-Control-Allow-Methods", "*"); next(); });
ポートフォリオ用に急いで書いたのと久々に書いたので
ブログとしては最悪な感じだなぁ
定期的に書く余裕をもつこととユーザー目線に立つことと心がけよう,,,