やったこと
今回はReactを用いて電卓を実装しました。
完成後はこのような見た目になっています。
実装コード
App.js
import logo from './logo.svg';
import './App.css';
import { useState } from 'react';
function App() {
const [result, setResult] = useState("");
const handleCalculation = (number) => {
const newResult = result + number;
setResult(newResult);
};
const handleReset = () => {
setResult("");
}
const execCalculation = () => {
try {
setResult(eval(result));
} catch (error) {
setResult("Error!");
}
}
return (
<div className="App">
<h1>Dentaku!!!</h1>
<p className='string-box'>{result}</p>
<div className='column-box'>
<div className='row-box'>
<button className='normal' onClick={() => handleCalculation("7")}>7</button>
<button className='normal' onClick={() => handleCalculation("8")}>8</button>
<button className='normal' onClick={() => handleCalculation("9")}>9</button>
<button className='normal' onClick={() => handleCalculation("*")}>*</button>
</div>
<div className='row-box'>
<button className='normal' onClick={() => handleCalculation("4")}>4</button>
<button className='normal' onClick={() => handleCalculation("5")}>5</button>
<button className='normal' onClick={() => handleCalculation("6")}>6</button>
<button className='normal' onClick={() => handleCalculation("-")}>-</button>
</div>
<div className='row-box'>
<button className='normal' onClick={() => handleCalculation("1")}>1</button>
<button className='normal' onClick={() => handleCalculation("2")}>2</button>
<button className='normal' onClick={() => handleCalculation("3")}>3</button>
<button className='normal' onClick={() => handleCalculation("+")}>+</button>
</div>
<div className='row-box'>
<button className='normal' onClick={() => handleCalculation("0")}>0</button>
<button className='normal' onClick={() => handleCalculation(".")}>.</button>
<button className='normal' onClick={() => handleCalculation("/")}>/</button>
<button className='normal' onClick={() => execCalculation()}>=</button>
</div>
<div className='row-box'>
<button className='reset-button' onClick={() => handleReset()}>Reset</button>
</div>
</div>
</div>
);
}
export default App;
App.css
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.column-box {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
flex-flow: column;
}
.row-box {
display: flex;
align-items: center;
margin: 5px;
}
.child-box {
justify-content: center;
}
div.row-box > button.normal {
width: 50px;
height: 50px;
margin: 1px;
font-size: large;
}
.reset-button {
width: 100px;
height: 50px;
margin: 1px;
font-size: large;
}
.string-box {
background-color: lavender;
margin: 10px;
border: 1px solid;
border-radius: 5px;
padding: 20px;
display: inline-block;
min-width: 180px;
}
eval()について
今回はeval()を用いて実装しました。理由は、inputがボタンからのみ行われるからです。ただ、今後のためにevalの脆弱性について調べました。
evalは任意のjavascriptを実行できるという点が危険です。例えば、入力が他の場所で使っている変数を破壊したり、無限ループに入ったりすることもできます。
終わりに
今回はevalの脆弱性について勉強できました。これからもReactの開発を通して勉強していきます。