SID
SID

Reputation: 57

A reactjs module for incrementing the count on the press of a button -

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

Answers (2)

Yury Tarabanko
Yury Tarabanko

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

Sombriks
Sombriks

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

Related Questions