I’ve been working on my JavaScript calculator using create-react-app
and editing on my LocalHost. With lots of browsing through CodePen and Medium, I’ve now got a setup that mostly works, except that I can’t actually display results. When I press the numbers, I see them entered on the display, and when I press the Clear button, the display is cleared.
When I press Equals, however, nothing happens! Then, if I press Equals then Clear, I get an error message: “TypeError: this.setState is not a function.” I googled this error, and it seems like it pops up when you have functions in a React Component that aren’t bound to the constructor…but I do have my functions bound to the constructor (I think I do, at least).
Any brilliant ideas would be most welcome!
Here is the JS. I can give HTML/CSS as well, but I’m guessing this is a JS issue, so we’ll start there:
import React, { Component } from 'react';
import update from 'immutability-helper';
import math from 'mathjs';
import './App.scss';
class Calculator extends Component {
constructor(props) {
super(props);
this.state = {
operations: [],
}
this.handleClick = this.handleClick.bind(this);
this.calculateOperations = this.calculateOperations.bind(this);
}
calculateOperations() {
let result = this.state.operations.join('')
if (result) {
result = math.eval(result);
result = math.format(result, {precision: 14})
result = String(result)
this.setState = ({
operations: [result]
})
}
}
handleClick(event) {
const value = event.target.getAttribute('data-value')
switch (value) {
case "clear":
this.setState({
operations: []
});
break;
case "=":
this.calculateOperations();
break;
default:
const newOperations = update(this.state.operations, {
$push : [value]
});
this.setState({
operations: newOperations
});
break;
}
}
render () {
return (
<div className="container text-center">
<div className="calculator">
<Display data={this.state.operations} />
<Buttons>
<div className="row">
<Button onClick={this.handleClick} label="1" id="one" value="1" />
<Button onClick={this.handleClick} label="2" id="two" value="2" />
<Button onClick={this.handleClick} label="3" id="three" value="3" />
<Operator onClick={this.handleClick} label="+" id="add" value="+" />
</div>
<div className="row">
<Button onClick={this.handleClick} label="4" id="four" value="4" />
<Button onClick={this.handleClick} label="5" id="five" value="5" />
<Button onClick={this.handleClick} label="6" id="six" value="6" />
<Operator onClick={this.handleClick} label="-" id="subtract" value="-" />
</div>
<div className="row">
<Button onClick={this.handleClick} label="7" id="seven" value="7" />
<Button onClick={this.handleClick} label="8" id="eight" value="8" />
<Button onClick={this.handleClick} label="9" id="nine" value="9" />
<Operator onClick={this.handleClick} label="*" id="multiply" value="*" />
</div>
<div className="row">
<Blank label="" id="" value="" />
<Button onClick={this.handleClick} label="0" id="zero" value="0" />
<Button onClick={this.handleClick} label="." id="decimal" value="." />
<Operator onClick={this.handleClick} label="/" id="divide" value="/" />
</div>
<div className="row">
<Clear onClick={this.handleClick} label="C" id="clear" value="clear" />
<Equals onClick={this.handleClick} label="=" id="equals" value="=" />
</div>
</Buttons>
</div>
</div>
);
}
}
class Button extends Component {
render() {
return (
<div className="Button btn btn-primary col-2" onClick={this.props.onClick} data-size={this.props.size} data-value={this.props.value}>
{this.props.label}
</div>
);
}
}
class Blank extends Component {
render() {
return (
<div className="Blank btn btn-secondary col-2" onClick={this.props.onClick} data-size={this.props.size} data-value={this.props.value}>
{this.props.label}
</div>
);
}
}
class Operator extends Component {
render() {
return (
<div className="Operator btn btn-warning col-3" onClick={this.props.onClick} data-size={this.props.size} data-value={this.props.value}>
{this.props.label}
</div>
);
}
}
class Clear extends Component {
render() {
return (
<div className="Clear btn btn-danger col-5" onClick={this.props.onClick} data-size={this.props.size} data-value={this.props.value}>
{this.props.label}
</div>
);
}
}
class Equals extends Component {
render() {
return (
<div className="Equals btn btn-success col-5" onClick={this.props.onClick} data-size={this.props.size} data-value={this.props.value}>
{this.props.label}
</div>
);
}
}
class Buttons extends Component {
render() {
return <div className="Buttons"> {this.props.children} </div>
}
}
class Display extends Component {
render() {
const string = this.props.data.join('')
return <div className="Display"> {string} </div>
}
}
export default Calculator;