Reputation: 57
a react component that will display the current value of our counter.
The counter should start at 0. There should be a button to add 1. There should also be a button to subtract 1.
I am unable to understand the problem, as to what is it that I have missed or some wrong syntax.
const React = require('react');
class Counter extends React.Component{
constructor(...args){
super(...args);
this.state = { counter: 0 };
}
// Your event handlers
cincrement = () => {
this.setState({ counter: this.state.counter+1 });
};
cdecrement = () => {
this.setState({ counter: this.state.counter-1 });
};
render() {
return (
<div>
<h1>{this.state.counter}</h1>
<button type="button" onClick={this.cincrement}>
Decrement
</button>
<button type="button" onClick={this.cdecrement}>
Increment
</button>
</div>
)
}
}
The error that I get on running the code
/runner/node_modules/babel-core/lib/transformation/file/index.js:590 throw err; ^
SyntaxError: /home/codewarrior/index.js: Unexpected token (16:13) 14 | // Your event handlers 15 |
16 | cincrement = () => { | ^ 17 | this.setState({ counter: this.state.counter+1 }); 18 | }; 19 |
at Parser.pp$5.raise (/runner/node_modules/babylon/lib/index.js:4454:13) at Parser.pp.unexpected (/runner/node_modules/babylon/lib/index.js:1761:8) at Parser.pp$1.parseClassProperty (/runner/node_modules/babylon/lib/index.js:2571:50) at Parser.parseClassProperty (/runner/node_modules/babylon/lib/index.js:6157:20) at Parser.pp$1.parseClassBody (/runner/node_modules/babylon/lib/index.js:2516:34) at Parser.pp$1.parseClass (/runner/node_modules/babylon/lib/index.js:2406:8) at Parser.pp$1.parseStatement (/runner/node_modules/babylon/lib/index.js:1843:19) at Parser.parseStatement (/runner/node_modules/babylon/lib/index.js:5910:22) at Parser.pp$1.parseBlockBody (/runner/node_modules/babylon/lib/index.js:2268:21) at Parser.pp$1.parseBlock (/runner/node_modules/babylon/lib/index.js:2247:8)
Upvotes: 0
Views: 507
Reputation: 45121
It seems your babel config does not include class properties syntax
You could use normal prototype methods and then prebind them in constructor
Also since your next state depends on the prev state you should pass a callback to setState
const React = require('react');
class Counter extends React.Component{
constructor(...args){
super(...args);
this.state = { counter: 0 };
this.cincrement = this.cincrement.bind(this);
this.cdecrement= this.cdecrement.bind(this)
}
// Your event handlers
cincrement(){
this.setState(state => ({ counter: state.counter+1 }));
}
cdecrement() {
this.setState(state => ({ counter: state.counter-1 }));
}
render() {
return (
<div>
<h1>{this.state.counter}</h1>
<button type="button" onClick={this.cincrement}>
Decrement
</button>
<button type="button" onClick={this.cdecrement}>
Increment
</button>
</div>
)
}
}
Upvotes: 1
Reputation: 3622
React needs binding on event handlers.
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
One way to avoid this is to define the handlers inside the constructor:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = ev => {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
Your original code, IIRC, needs a special babel plugin to work.
Upvotes: 0