Reputation:
So I'm pretty new to React (and JS) in general. Normally code with Java or C# and I'm not used to the syntax just yet. I did manage to make a simple calculator with React and wanna add the functionality but whenever I try, I get an error that says that my method is not defined.
Basically the function is used to get the prop from my Button component and append it into the Screen component value.
class Button extends React.Component {
constructor(props) {
super(props)
}
add(button) {
let value = button.value
let text = document.getElementByID('screenInput').value
if (value == '=') {
document.getElementById('screenInput').innerHTML = eval(text).toString();
} else if (value == 'C') {
document.getElementById('screenInput').innerHTML = '0':
} else if (value == '+/-' && text != '0') {
document.getElementById('screenInput').innerHTML = `` - (${ text })``;
} else if (value == '\d' || (text.slice(-1) != value && text != '0')) {
document.getElementById('screenInput').innerHTML = text.append(value);
}
}
render() {
return (
<button type='button' value={this.props.value} onClick={() => add(this)}> {this.props.value}</button >
)
}
}
https://jsfiddle.net/q7yakt1v/22/`
Upvotes: 0
Views: 1213
Reputation: 2048
As pointed out in a couple of the other answers, the key issue with your code is onClick={() => add(this)}
. But I think this is because of a misunderstanding of how state is handled in React.
I have lifted the state of the value of screen into the <Calculator />
component. This way we pass the state into the <Screen />
component to display it and can manipulate it from the <Buttons />
component without calling the DOM directly (as @Avanthika pointed out in their answer).
class Calculator extends React.Component {
constructor(props) {
super(props)
this.state = {
value: '0'
}
this.handleButtonClick = this.handleButtonClick.bind(this)
}
handleButtonClick(value) {
const { value: currentValue } = this.state;
let newValue;
if (value == '=') {
newValue = eval(currentValue).toString();
} else if (value == 'C') {
newValue = 0;
} else if (value == '+/-' && currentValue != '0') {
newValue = `-(${text})`;
} else if (currentValue === '0') {
newValue = value;
} else {
newValue = currentValue.concat(value);
}
this.setState({ value: newValue });
}
render() {
const { value } = this.state;
return (
<div id="body">
<Screen value={value} />
<Buttons onButtonClick={this.handleButtonClick} />
</div>
)
}
}
....
const Button = ({ value, onClick }) => (
<button type="button" onClick={() => onClick(value)}>
{value}
</button>
)
I have renamed your function add
and changed its behaviour. Instead of getting/updating the values to DOM, it uses the state in the <Calculator />
component.
You can see the working code here: https://jsfiddle.net/zvxpkq46/
Upvotes: 0
Reputation: 2928
So the reason you can't just refer to add like that is it intrinsically bound to the instance of your class Button
. So if you want to call it, you'd have to do this.add(this)
.
The problem you will run into next is that the this
you are passing to add
isn't the button element, but a reference to the class instance.
I guess I should also add that you don't want to be modifying the DOM directly outside of React like that because React internally keeps track of changes. You should prefer using state/context to apply changes to things outside the immediate scope your component.
Upvotes: 1
Reputation: 4182
add = (button) => {
let value = this.buttonRef.value;
// rest of your code
}
render() {
return (
<button ref={(button) => { this.buttonRef = button; }} type="button" value={this.props.value} onClick={() => this.add()}>
{this.props.value}
</button>
);
}
Upvotes: 0
Reputation: 867
class Button extends React.Component {
constructor(props) {
super(props);
}
add() {
let value = this.value;
let text = document.getElementByID("screenInput").value;
if (value == "=") {
document.getElementById("screenInput").innerHTML = eval(text).toString();
} else if (value == "C") {
document.getElementById("screenInput").innerHTML = "0";
} else if (value == "+/-" && text != "0") {
document.getElementById("screenInput").innerHTML = `-(${text})`;
} else if (value == "d" || (text.slice(-1) != value && text != "0")) {
document.getElementById("screenInput").innerHTML = text.append(value);
}
}
render() {
return (
<button type="button" value={this.props.value} onClick={() => this.add()}>
{this.props.value}
</button>
);
}
}
Upvotes: 0