Reputation: 1153
I have a react calculator with basic functionality (+-/) and the way I wanted to do it is that you see the result, not after pressing =, but when pressing any operator (+-/). My problem is that I cant figure out a good way to deal with numbers bigger then 9 and whatever I try, I either mess up result or what I show. Any help would be really great. Thanks!!
I also put it on codepen so its better to see: https://codepen.io/julianyc/pen/bXwxbg?editors=1010
const math_it_up = {
'+': function (x, y) {
return x + y
},
'-': function (x, y) {
return x - y
},
'*': function (x, y) {
return x * y
},
'/': function (x, y) {
return x / y
}
}
class App extends React.Component {
state = {
result: 0,
operator: "",
currentNum: "",
show: 0
};
onClick = (elem) => {
if (isNaN(elem)) {
if (elem === "=") {
this.setState({
show: this.state.result
})
} else {
this.setState({
operator: elem,
show: this.state.result ? this.state.result : null
})
}
}
else {
if (!this.state.currentNum) {
this.setState({
currentNum: parseInt(elem),
result: parseInt(elem),
show: elem
})
} else {
if (this.state.operator) {
this.setState({
currentNum: parseInt(elem),
result: math_it_up[this.state.operator](this.state.result, parseInt(elem)),
show: elem
})
}
}
}
};
render() {
return (
<div>
<Key onClick={this.onClick}/>
<h1>{this.state.show}</h1>
</div>
)
}
}
const Key = ({onClick}) => {
const renderNumbers = () => {
const arr = [0,1,2,3,4,5,6,7,8,9];
return arr.map((val, i) => {
return <button key={i} name={val} onClick={(e) => onClick(e.target.name)}>{val}</button>
})
};
const renderCalculationKeys = () => {
const arr = ["+", "-", "/", "*", "="];
return arr.map((val, i) => {
return <button key={i} name={val} onClick={(e) => onClick(e.target.name)}>{val}</button>
})
};
return (
<div>
{renderNumbers()}
{renderCalculationKeys()}
</div>
)
};
Upvotes: 2
Views: 532
Reputation: 429
Try to use logic similar to this. Of course, you can make this in thousands of different ways, this is just one of them.
I think the code is self-explanatory. Basically, you add the number you entered to the end of the number saved in the state, and if the string is 0, you override it with the number you entered.
const Calculate = {
'+': (x, y) => x + y,
'-': (x, y) => x - y,
'*': (x, y) => x * y,
'/': (x, y) => x / y
}
const Keys = ({ onClick, operator }) => {
return (
<div className="buttons">
{[1,2,3,'+',4,5,6,'-',7,8,9,'/','C',0,'=','*'].map(val => {
return (
<button
key={val.toString()}
name={val}
onClick={(e) => onClick(e.target.name)}
className={operator && operator === val ? 'is-active' : ''}
>
{val}
</button>
)
})}
</div>
)
}
const App = () => {
const [x, setX] = React.useState(0);
const [y, setY] = React.useState(null);
const [operator, setOperator] = React.useState(null);
const onClick = n => {
const operators = ['-','+','*','/']
if (isNaN(n)) {
if (operators.includes(n)) {
if (y !== null) {
setX(Calculate[operator](x, y))
setY(null)
}
setOperator(n)
}
if (n === 'C') {
setX(0)
setY(null)
setOperator(null)
}
if (n === '=' && y !== null) {
setX(Calculate[operator](x, y))
setY(null)
setOperator(null)
}
} else {
const setNumber = (v, n) => {
if (v === 0 || v === null) v = ''
return parseInt(v.toString() + n)
}
if (operator !== null || y !== null) setY(setNumber(y, n))
else setX(setNumber(x, n))
}
}
return (
<div className="calculator">
<h1 className="display">{y !== null ? y : x}</h1>
<Keys onClick={onClick} operator={operator && y === null ? operator : null}/>
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono:300&display=swap');
html {
font-size: 6px;
}
body {
background: #111;
font-family: 'Roboto Mono';
font-weight: 300;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
}
#root {
position: absolute;
min-height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
}
* {
margin: 0;
padding: 0;
font: inherit;
box-sizing: border-box;
}
body button {
-moz-appearance: none;
-webkit-appearance: none;
background-color: transparent;
border-radius: 0;
margin: 0;
padding: 0;
}
*:focus {
outline: none;
}
.calculator {
width: 100%;
max-width: 40rem;
border: none;
background: #000;
}
.display {
padding: 1.5rem 1.5rem;
text-align: right;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
background-color: #000;
font-size: 4rem;
color: #fff;
line-height: 1;
}
.buttons {
display: flex;
flex-flow: row wrap;
width: 100%;
}
.buttons button {
transition: background 200ms ease, color 200ms ease;
flex: 0 0 25%;
line-height: 5rem;
border: none;
border-top: 1px solid #000;
border-right: 1px solid #000;
color: #fff;
font-size: 2.5rem;
background-color: #424242;
}
.buttons button:active {
background-color: #626262;
}
.buttons button:nth-child(4n+4) {
background-color: #f09214;
border-right: none;
}
.buttons button:nth-child(4n+4):active {
background-color: #f7a434;
}
.buttons button.is-active {
background-color: #fff;
color: #f09214;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 3