1

I'm trying to update the state of my component based on key inputs, and pass it to another component.

I can get call keyboardInput() and console.log the correctly when one of the arrow keys are pressed, however I cannot get the returned value to render in <p>The current input is: {this.keyboardInput}</p>

E.g. return {'Y': 1}; when the up key is pressed, but nothing appears in the <p> element

I believe I'm missing some understanding when it comes to the componentWillReceiveProps function, but I'm at a loss.

Could it be that keyboardInput is returning an object not a string value? But even when I change the return to just be a string, I still cannot get it to render.

What am I missing here?

Thanks,

class GameBoard extends Component {

    constructor(props) {
        super(props);
        this.state = {
            test: {},
        };
    }

    // Captures event from main window
        keyboardInput = (e) => {

            const code = e.keyCode ? e.keyCode : e.which;

            // Change X and Y values
            if (code === 38) { //up key
                return {'Y': 1};
            } else if (code === 40) { //down key
                return {'Y': -1};
            } else if (code === 37) { // left key
                return {'X': 1};
            } else if (code === 39) { // right key
                return {'X': -1};
            }
        };

    componentWillMount() {
        window.addEventListener('keydown', this.keyboardInput);
    }

    componentWillUnmount() {
        window.removeEventListener('keydown', this.keyboardInput);
    }

    componentWillReceiveProps(nextProps) {
        this.setState.test = this.keyboardInput(nextProps);
    }

    render() {

        return (
            <div>
                <p>The current input is: {this.keyboardInput}</p>
                <Ball/>
            </div>
        )
    }

}

class App extends Component {

  render() {

      const boardStyle = {
          'position': 'absolute',
          'backgroundColor': '#7f8c8d',
          'height': '100%',
          'width': '100%',

      };

    return (
      <div>
        <header>
          <h1 className="App-title">Welcome to Moving Objects</h1>
        </header>
          <div style={boardStyle}>
              <GameBoard/>
          </div>
      </div>
    );
  }
}

export default App;
1
  • 1
    Props are passed down from the parent component. They are irrelevant here. What you'll want to do is actually change the state inside keyboardInput, as opposed to returning the object into nirvana. (nowhere). You need to 1. look up how setState() is used 2. do that inside your keyboardInput Commented Dec 24, 2017 at 1:08

1 Answer 1

2

Looks like there's some misunderstanding about React/JS constructs in general here.

Hopefully the below will help you along, but you should definitely take a closer look at the React docs to get a better handle on what you're doing.

{this.keyboardInput} in your render function doesn't actually refer to anything here - this is referring to your GameBoard class, and then you're trying to access some member - be it a function, variable, whatever - called keyboardInput. You don't have one.

With React, what you would want to access is {this.state.keyboardInput} - what that is saying is this: In this (the GameBoard), I want to access its current state. In that state, there is a field called keyboardInput. Render that.

<p> The current input is: {this.state.keyboardInput} </p>

The second step is to actually set that state. It looks like you have calling your function keyboardInput down when the eventlistener picks up an event, but I think this is part of your issue: keyboardInput would be much better named something like onKeyboardInput or handleKeyboardInput.

Remember how we wanted to set the state? Inside that function, we're going to have to use React's setState function - it would look something like this:

handleKeyboardInput = (e) => {
        const code = e.keyCode ? e.keyCode : e.which;

        if (code === 38) { //up key
            this.setState({ keyboardInput: {'Y', -1 }});
        }
}

This function is now saying, "Hey GameBoard, your state is going to now have a field keyboardInput, which will look like the object { 'Y', -1 }."

Note that this in keyboardInput wants to refer to React's component, so we'll have to bind this in our listeners:

componentWillMount() {
        window.addEventListener('keydown', this.handleKeyboardInput.bind(this));
}

All we're doing here is telling handleKeyboardInput to use the same this as componentWillMount. this in componentWillMount refers to our GameBoard component, so this in handleKeyboardInput will also refer to the GameBoard. We want this because handleKeyboardInput wants to call GameBoard's .setState function.

In general, that's how the flow of React goes: you'll want to set some state on a component using setState. After that's done, you can read it out in your render function (or any other function for that matter) by saying this.state.foobar.

In this example, we start at our listener. We see a keypress event, and say, go handle whatever we need to do at handleKeyboardInput! handleKeyboardInput says GameBoard! Your state is keyboardInput: foo. All the while, render is looking GameBoard's state (the keyboardInput!) to display.

Like I said, this is a pretty informal rundown of states in React - definitely take a look at React's documentation, and maybe work through an example project they have to really let it sink in.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for explaining this. I'll look over the docs some more. Cheers!
why don't you bound the handleKeyboardInput method in the constructor?

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.