Reputation: 11
I am making a very simple calculator in React, and I am very new to JS and React js.
So, this code just tries to add a few numbers and returns them in H1.
import React, { Component } from "react";
class App extends React.Component {
state = {
num1: 0,
num2: 0,
answer: 5,
};
count = (number) => {
this.setState({ num1: number });
return number;
};
count2 = (number2) => {
this.setState({ num2: number2 });
return number2;
};
count3 = () => {
this.setState({ answer: this.count() + this.count2() });
console.log(this.state.answer);
console.log(this.count2());
return this.state.answer;
};
render() {
return (
<div>
<div>
<h1>{this.state.num1}</h1>
<button onClick={() => this.count(1)}> 1 </button>
<button onClick={() => this.count(2)}> 2 </button>
<button onClick={() => this.count(3)}> 3 </button>
<button onClick={() => this.count(4)}> 4 </button>
<button onClick={() => this.count(5)}> 5 </button>
<button onClick={() => this.count(6)}> 6 </button>
<button onClick={() => this.count(7)}> 7 </button>
</div>
<div>
<h1>{this.state.num2}</h1>
<button onClick={() => this.count2(1)}> 1 </button>
<button onClick={() => this.count2(2)}> 2 </button>
<button onClick={() => this.count2(3)}> 3 </button>
<button onClick={() => this.count2(4)}> 4 </button>
<button onClick={() => this.count2(5)}> 5 </button>
<button onClick={() => this.count2(6)}> 6 </button>
<button onClick={() => this.count2(7)}> 7 </button>
</div>
<div>
<button onClick={() => this.count3()}>click</button>
<h1>{this.state.answer}</h1>
</div>
</div>
);
}
}
export default App;
So, currently the answer is returning NaN after clicking it. Why is it happening so, and how to fix it?
Upvotes: 0
Views: 1372
Reputation: 63550
Your count
methods expect a number passed as an argument but you're not supplying them so state gets updated with undefined
in each case, so your answer is NaN
.
Have each method simply update the state (no need to return anything from them) and then have count3
update the state with those two numbers.
const { Component } = React;
class App extends React.Component {
state = { num1: 0, num2: 0, answer: 5 };
count = (number) => {
this.setState({ num1: number });
};
count2 = (number2) => {
this.setState({ num2: number2 });
};
count3 = () => {
const { num1, num2 } = this.state;
this.setState({ answer: num1 + num2 });
};
render() {
return (
<div>
<div>
<h1>{this.state.num1}</h1>
<button onClick={() => this.count(1)}> 1 </button>
<button onClick={() => this.count(2)}> 2 </button>
<button onClick={() => this.count(3)}> 3 </button>
<button onClick={() => this.count(4)}> 4 </button>
<button onClick={() => this.count(5)}> 5 </button>
<button onClick={() => this.count(6)}> 6 </button>
<button onClick={() => this.count(7)}> 7 </button>
</div>
<div>
<h1>{this.state.num2}</h1>
<button onClick={() => this.count2(1)}> 1 </button>
<button onClick={() => this.count2(2)}> 2 </button>
<button onClick={() => this.count2(3)}> 3 </button>
<button onClick={() => this.count2(4)}> 4 </button>
<button onClick={() => this.count2(5)}> 5 </button>
<button onClick={() => this.count2(6)}> 6 </button>
<button onClick={() => this.count2(7)}> 7 </button>
</div>
<div>
<button onClick={() => this.count3()}>click</button>
<h1>{this.state.answer}</h1>
</div>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
There is a slightly more concise version of your code that you may find useful. It involves using a loop to add the buttons, and attaching only one listener to the parent div. The listener will catch the button events as they bubble up the DOM, and you can use data attributes from the parent and the button to update the specific state property.
(The even more "React Way" would be identify those parts of your JSX that repeat, and maybe to create reusable Number
and NumberGroup
components; but that's code for another day.)
const { Component } = React;
class App extends React.Component {
state = { num1: 0, num2: 0, answer: 0 };
// Take the group id from the parent dataset,
// and the id from the button that was clicked,
// and use that information to update the state
// Note: in this example, because we're using a
// data attribute (a string) we need to coerce it
// to a number
handleClick = (e) => {
const { group } = e.target.parentNode.dataset;
const { id } = e.target.dataset;
this.setState({ [group]: Number(id) })
}
// Return an array of seven buttons each
// with their own id
getButtons = () => {
const buttons = [];
for (let i = 1; i <= 7; i++) {
buttons.push(<button data-id={i}>{i}</button>);
}
return buttons;
}
// When the "Update total" button is clicked
// get the numbers from state and update the total
updateTotal = () => {
const { num1, num2 } = this.state;
this.setState({ answer: num1 + num2 })
}
render() {
return (
<div>
<div data-group="num1" onClick={this.handleClick}>
<h3>{this.state.num1}</h3>
{this.getButtons()}
</div>
<div data-group="num2" onClick={this.handleClick}>
<h3>{this.state.num2}</h3>
{this.getButtons()}
</div>
<div class="answer">
<button onClick={this.updateTotal}>Update total</button>
<h3>Total: {this.state.answer}</h3>
</div>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('react')
);
.answer { margin-top: 1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Upvotes: 3
Reputation: 402
maybe you can try change your count3
method like this:
count3 = () => {
this.setState({ answer: this.state.num1 + this.state.num2 });
return this.state.answer;
};
then when you click button trigger count3
function to setState answer based on your state.num1
and state.num2
and the answer will be change.
Upvotes: 0