自分用のメモ
Contents
環境の準備
実行環境
- VS code:v1.62.3
- Node.js:v14.17.3
- React:v17.0.2
- Typescript:v4.1.6
プロジェクトの作成(Typescriptで作成)
Next Create Appで作成します。
pagesフォルダ配下のソース
- 9~16行目の内容が、Layoutコンポーネントの中で「props.children」で参照できます。
import type { NextPage } from 'next'
import Calc from './components/Calc'
import Layout from './components/layout'
const Home: NextPage = () => {
return (
<div>
<Layout title='Calculator'>
<div className='text-center'>
<Calc />
</div>
</Layout>
</div>
)
}
export default Home
pages/api配下のソース
- 内部のAPI経由でjsonDataを取得する処理です。
import type { NextApiRequest, NextApiResponse } from 'next'
import jsonData from '../components/jsonData'
type Data = {
data: any
}
const handler = (req: NextApiRequest, res: NextApiResponse<Data>) => {
res.status(200).json(jsonData)
}
export default handler
pages/components配下のソース
ページを構成するレイアウト
- Layoutコンポーネントについては、こちらの記事を参考にしてください。
ボタンとアクションの記述
- 各ボタンの処理を記述しています。
export default {
'data': {
'tax': {
'caption': '入力した金額から消費税(10%)価格を計算します。',
'function': '(...param) => {return Math.floor(param[0] * 1.1)}'
},
'tax2': {
'caption': '入力した金額から軽減税率(8%)価格を計算します。',
'function': '(...param) => {return Math.floor(param[0] * 1.08)}'
},
'total': {
'caption': '10,20,30...というようにカンマで区切った数字の合計を計算します。',
'function': `(...param) => {
let re = 0
for (let i = 0; i < param[0].length; i++) {
re += parseInt(param[0][i])
}
return re
}`
},
'factorial': {
'caption': 'ゼロから入力値までの合計を計算します。',
'function': `(...param) => {
console.log(param)
let re = 0
for (let i = 0; i <= param[0]; i++) {
re += i
}
return re
}`
}
}
}
- 11行目のuseEffectでjsonDataを取得しちえます。
- 53~58行目で、jsonDataに記載されたボタンとアクションが作成されます。
- 68行目は、履歴クリアボタンです。
import { useState, useEffect } from "react"
const Calc = (props: any) => {
const [message, setMessage] = useState('')
const [input, setInput] = useState('')
const [data, setData] = useState<string[]>([])
const [func, setFunc] = useState({data:{}})
const fetchFunc = (address: string) => {
return fetch(address).then(res => res.json())
}
useEffect(() => {
fetchFunc('/api/func')
.then((r) => setFunc(r))
}, [data])
const onChange = (e: any) => {
setInput(e.target.value)
}
const onKeyPress = (e: any) => {
if (e.key == 'Enter') {
doAction(e)
}
}
const doAction = (e: any) => {
const res = eval(input)
setMessage(res)
data.unshift(input + ' = ' + res)
setData(data)
setInput('')
}
const clear = (e: any) => {
setData([])
setMessage('Clear history.')
}
const doFunc = (e: any) => {
const arr = input.split(',')
const fid = e.target.id
const f = func.data[fid]
const fe = eval(f.function)
const res = fe(arr)
setMessage(res)
data.unshift(fid + ' = ' + res)
setData(data)
setInput('')
}
return (
<div>
<div className="alert alert-primary">
<h5>Result: {message}</h5>
<div className="form-group">
<input type='text' value={input} className="form-control"
onChange={onChange} onKeyPress={onKeyPress} />
</div>
{Object.entries(func.data).map((value, key) =>
<button className="btn btn-secondary m-1" key={key}
title={value[1].caption} id={value[0]} onClick={doFunc} >
{value[0]}
</button>
)}
</div>
<table className="table">
<thead><tr><th>History:</th></tr></thead>
<tbody>
{data.map((value, key) =>
<tr key={key}><td>{value}</td></tr>
)}
</tbody>
</table>
<button onClick={clear} className="btn btn-warning">
Clear History
</button>
</div>
)
}
export default Calc
あとがき
特になし
コメントを残す