0

I'm trying to learn me some React but can't seem to understand it.
How would I access this.state.planet in newMove()?
Uncaught TypeError: Cannot read property 'state' of undefined is what I get.

Here is app.js

export default class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = newPlay();
  }

  render() {
    return (
      <div>
        <button onClick={(e) => newMove(e)}>New Move</button>
      </div>
    );
  }
}

and here is logic.js

export const newPlay = () => ({
  planet: 'Earth',
  position: [0, 0, 0, 0, 0, 0, 0, 0, 0],
  active: true,
  shots: 5
});

export const newMove = () => {
  let player = this.state.planet === 'Earth' ? 'Human' : 'Alien';
  console.log(player);
  this.setState({
    shots: this.state.shots++,
    active: false
  })
}
2
  • You need to learn how this and arrow functions work. That has nothing to do with React but basic JavaScript. When you call the function with newMove(e), how should JavaScript know that this should refer to your component instance? I recommend to read developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Apr 30, 2018 at 21:48
  • Besides the issue with this, you don't want to update the components state based on this.state. Pass a function to setState instead. See reactjs.org/docs/react-component.html#setstate . Commented Apr 30, 2018 at 22:05

1 Answer 1

2

To make this work as intended in the newMove function, you have to bind it to the class instance this in your constructor method.

Note that you can't use arrow notation syntax for newMove. Arrow functions don't support rebinding this. Use function instead.

export function newMove() { 
  ...
}

Then bind it in the App class, and use the bound this.newMove in your onClick prop.

export default class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = newPlay();
    this.newMove = newMove.bind(this); 
  }

  render() {
    return (
      <div>
        <button onClick={this.newMove}>New Move</button>
      </div>
    );
  }
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for your input, even after going this way I get the error, "Uncaught TypeError: Cannot read property 'state' of undefined". It's about the line in newMove, "let player = this.state.planet === 'Earth' ? 'Human' : 'Alien';"
@Shamaran: Seems like you forgot to updated the function definition to a non-arrow function.
Thanks guys, I posted comment and missed the update!
I don't think that it is good practice to have code external to the class modifying its state. It would be better to make newMove an instance method of the App.
@murrayju Why do you think that is bad practice? And what do you mean by "external code"? Is it ok to use class inheritance, or should we define our own Component.setState as well?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.