user3696212 user3696212 - 6 months ago 33
Javascript Question

Unable to access React instance (this) inside event handler

I am writing a simple component in ES6 (with BabelJS), and functions this.setState and React.refs.something are not working. Do you know why? Here is the code:

import React from 'react'

class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {inputContent: 'startValue'}
}

sendContent(e) {
console.log('sending input content '+React.findDOMNode(React.refs.someref).value)
}

changeContent(e) {
this.setState({inputContent: e.target.value})
}

render() {
return (
<div>
<h4>The input form is here:</h4>
Title:
<input type="text" ref="someref" value={this.inputContent}
onChange={this.changeContent} />
<button onClick={this.sendContent}>Submit</button>
</div>
)
}
}

export default SomeClass


There are 2 main problems:


  1. When changing the value of the input, this.setState doesn't change the state, so the field acts as read-only

  2. When sending input console says 'cant read property of someref'


Answer

this.changeContent needs to be bound to the component instance via this.changeContent.bind(this) before being passed as the onChange prop, otherwise the this variable in the body of the function will not refer to the component instance but to window. See Function::bind.

When using React.createClass instead of ES6 classes, every non-lifecycle method defined on a component is automatically bound to the component instance. See Autobinding.

Be aware that binding a function creates a new function. You can either bind it directly in render, which means a new function will be created every time the component renders, or bind it in your constructor, which will only fire once.

constructor() {
  this.changeContent = this.changeContent.bind(this);
}

vs

render() {
  return <input onChange={this.changeContent.bind(this)} />;
}

Refs are set on the component instance and not on React.refs: you need to change React.refs.someref to this.refs.someref. You'll also need to bind the sendContent method to the component instance so that this refers to it.

Comments