2

I have been trying to learn React with Redux the past couple of weeks. I can't seem to pass down an action as a property correctly as when I run it I get a "cannot read property "props" of null. However finding some code online I was able to try it out using es5 syntax and it worked. Does anyone understand what I am doing wrong in es6 and how I can make it work? Below is my attempt at es6 which does not work with the es5 style commented out which does work.

import React, { Component, PropTypes } from 'react'

export default class InputFoo extends Component {
  //export default React.createClass({

    submitHandler(evt){
    evt.preventDefault()
    const { inputFooAction } = this.props

    inputFooAction(evt.target[0].value);
  }
  //,

  render() {
    const { input } = this.props
    return (<div>
              <h1>Oh hey from inside the component {input}</h1>
              <form onSubmit={this.submitHandler}>
                <input type="text" id="theInput"/>
              </form>

             </div>)
  }
}// )

//block below is commented out for es5
InputFoo.propTypes = {
  inputFooAction: PropTypes.func,
  input: PropTypes.string 
}
E_net4
  • 27,810
  • 13
  • 101
  • 139
Peter3
  • 2,549
  • 4
  • 20
  • 40
  • It would probably be clearer if you put the ES2015 code in one snippet and the (working) ES5 solution in another one. Also, please include where the error occurs. – E_net4 Sep 28 '16 at 13:13
  • Possible duplicate of [Unable to access React instance (this) inside event handler](http://stackoverflow.com/questions/29577977/unable-to-access-react-instance-this-inside-event-handler) – E_net4 Sep 28 '16 at 13:17
  • There were a lot of great answers supplied. I really appreciate the time. Multiple answers were correct and I chose the one who answered first as the tie breaker. I didn't realize that I needed to attach the function to this manually. Thanks everyone! – Peter3 Sep 28 '16 at 13:35

5 Answers5

2

I've prepared a demo for you here: http://codepen.io/PiotrBerebecki/pen/dpRdKP

There is no autobinding ES6 classess so your onSubmit event needs to be handled as follows:

<form onSubmit={this.submitHandler.bind(this)}>

or even better:

constructor() {
  super();
  this.submitHandler = this.submitHandler.bind(this)
}
// then you can 
<form onSubmit={this.submitHandler}>

Here is the full code which demonstrates passing data from the input field found in the child component (InputFoo) to the parent component (App):

class App extends React.Component {
  constructor() {
    super();
    this.handleData = this.handleData.bind(this);
    this.state = {
      fromChild: ''
    };
  }

  handleData(data) {
    this.setState({
      fromChild: data
    });
  }

  render() {
    return (
      <div>
        <InputFoo handlerFromParant={this.handleData} /> 
        <h5>Received by parent:<br />{this.state.fromChild}</h5>
      </div>
    );
  }
}


class InputFoo extends React.Component {
  constructor() {
    super();
    this.handleChange = this.handleChange.bind(this);
    this.submitHandler = this.submitHandler.bind(this);
    this.state = {
      inputField: ''
    };
  }

  submitHandler(evt) {
    evt.preventDefault();
    // pass the input field value to the event handler passed
    // as a prop by the parent (App)
    this.props.handlerFromParant(this.state.inputField);

    this.setState({
      inputField: ''
    });
  }

  handleChange(event) {
    this.setState({
      inputField: event.target.value
    });
  }

  render() {
    return (
      <div>
        <form onSubmit={this.submitHandler}>
          <input type="text" 
                 id="theInput" 
                 value={this.state.inputField} 
                 onChange={this.handleChange} />
          <input type="submit" />
        </form>
        <h5>Visible in child:<br />{this.state.inputField}</h5>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('app')
);
Piotr Berebecki
  • 7,428
  • 4
  • 33
  • 42
1

You forgot to bind this of the component to your event handler. There 3 ways to do it with ES6:

//most effient way 
constructor(props){
 super(props);
 this.submitHandler = this.submitHandler.bind(this);
}
OR
submitHandler = (e) => {....}
OR
render(){
     ...
      <form onSubmit={this.submitHandler.bind(this)}>
    ...

}
Phi Nguyen
  • 3,046
  • 14
  • 26
0

When using es2015 classes in React, you need to manually bind this to your class methods. You can do it in your constructor(which is recommended):

constructor(props) {
    super(props);
    this.submitHandler = this.submitHandler.bind(this);
}

or when setting your handler to your onSubmit prop:

<form onSubmit={this.submitHandler.bind(this)}>
slugo
  • 1,019
  • 2
  • 11
  • 22
0

Maybe you must call the super inside the constructor like this. This is made inside your class

constructor(props) { super(props); }

After that you may be able to use this.props.myProperty

Hope it works

Juan Rivillas
  • 897
  • 2
  • 9
  • 23
  • so I did try this earlier and that didn't do it. One of the below questions did though. Thanks for the input and time though! – Peter3 Sep 28 '16 at 13:22
0

With es2016, you need to manually bind this to your class method like :

constructor(props) {
 super(props);
 this.submitHandler = this.submitHandler.bind(this);
}

handler on form

<form onSubmit={this.submitHandler.bind(this)}>
Aatif Bandey
  • 1,193
  • 11
  • 14