React only binds Component methods to this - work around? - reactjs

Is there a way to avoid the boilerplate when using ES6 with react 0.14?
Until now I didn't have to worry about my function to be bound to the Component I created but that is no longer (why?!?) the case and the Component is only bounded to the Component super class (If I understood the errors correctly).
So what I really need to do each time I create a new class is to add this code to the constructor:
class CustomComp extends React.Component {
constructor() {
super();
this.newFunction = this.newFunction.bind(this);
}
newFunction(){
console.log('This is user defined function');
}
render() {
return <button onClick={this.newFunction}>Click</button>
}
}
So if I wont bind newFunction it will fail (no props, state or anything).
Is there a way to work around this?

From the React documentation:
No Autobinding
Methods follow the same semantics as regular ES6 classes, meaning that
they don't automatically bind this to the instance. You'll have to
explicitly use .bind(this) or arrow functions =>.
So, no there is not an automatic way to bind all methods that is new in 0.14. But, as the documentation suggests, you can:
1) use arrow functions (However, if you are using Babel, you need stage 0):
class CustomComp extends React.Component {
constructor() {
super();
}
newFunction = () => {
console.log('This is user defined function');
}
render() {
return <button onClick={this.newFunction}>Click</button>
}
}
2) you can bind in place:
class CustomComp extends React.Component {
constructor() {
super();
}
newFunction() {
console.log('This is user defined function');
}
render() {
return <button onClick={this.newFunction.bind(this)}>Click</button>
}
}
3) you can use an arrow function in place (which is like a bind):
class CustomComp extends React.Component {
constructor() {
super();
}
newFunction() {
console.log('This is user defined function');
}
render() {
return <button onClick={() => this.newFunction()}>Click</button>
}
}
I tend to use number 2 & 3 if I only have a 1-2 methods. Number 1 is good, but you have to remember the syntax for every method definition. If I have a lot of methods, I do tend to bind in the constructor.

Related

Put state value to function in React [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 2 years ago.
I am writing a simple component in ES6 (with BabelJS), and functions this.setState is not working.
Typical errors include something like
Cannot read property 'setState' of undefined
or
this.setState is not a function
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
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.
Morhaus is correct, but this can be solved without bind.
You can use an arrow function together with the class properties proposal:
class SomeClass extends React.Component {
changeContent = (e) => {
this.setState({inputContent: e.target.value})
}
render() {
return <input type="text" onChange={this.changeContent} />;
}
}
Because the arrow function is declared in the scope of the constructor, and because arrow functions maintain this from their declaring scope, it all works. The downside here is that these wont be functions on the prototype, they will all be recreated with each component. However, this isn't much of a downside since bind results in the same thing.
This issue is one of the first things most of us experience, when transitioning from the React.createClass() component definition syntax to the ES6 class way of extending React.Component.
It is caused by the this context differences in React.createClass() vs extends React.Component.
Using React.createClass() will automatically bind this context (values) correctly, but that is not the case when using ES6 classes. When doing it the ES6 way (by extending React.Component) the this context is null by default. Properties of the class do not automatically bind to the React class (component) instance.
Approaches to Solve this Issue
I know a total of 4 general approaches.
Bind your functions in the class constructor. Considered by many as a best-practice approach that avoids touching JSX at all and doesn't create a new function on each component re-render.
class SomeClass extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Bind your functions inline. You can still find this approach used here and there in some tutorials / articles / etc, so it's important you're aware of it. It it the same concept like #1, but be aware that binding a function creates a new function per each re-render.
class SomeClass extends React.Component {
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick.bind(this)}></button>
);
}
}
Use a fat arrow function. Until arrow functions, every new function defined its own this value. However, the arrow function does not create its own this context, so this has the original meaning from the React component instance. Therefore, we can:
class SomeClass extends React.Component {
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={ () => this.handleClick() }></button>
);
}
}
or
class SomeClass extends React.Component {
handleClick = () => {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Use utility function library to automatically bind your functions. There are a few utility libraries out there, that automatically does the job for you. Here are some of the popular, just to mention a few:
Autobind Decorator is an NPM package which binds methods of a class to the correct instance of this, even when the methods are detached. The package uses #autobind before methods to bind this to the correct reference to the component's context.
import autobind from 'autobind-decorator';
class SomeClass extends React.Component {
#autobind
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Autobind Decorator is smart enough to let us bind all methods inside a component class at once, just like approach #1.
Class Autobind is another NPM package that is widely used to solve this binding issue. Unlike Autobind Decorator, it does not use of the decorator pattern, but really just uses a function inside your constructor that automatically binds the Component's methods to the correct reference of this.
import autobind from 'class-autobind';
class SomeClass extends React.Component {
constructor() {
autobind(this);
// or if you want to bind only only select functions:
// autobind(this, 'handleClick');
}
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
PS: Other very similar library is React Autobind.
Recommendation
If I were you, I would stick with approach #1. However, as soon as you get a ton of binds in your class constructor, I would recommend you to explore one of the helper libraries mentioned in approach #4.
Other
It's not related to the issue you have, but you shouldn't overuse refs.
Your first inclination may be to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy.
For similar purposes, just like the one you need, using a controlled component is the preferred way. I suggest you to consider using your Component state. So, you can simply access the value like this: this.state.inputContent.
Although the previous answers have provided the basic overview of solutions (i.e. binding, arrow functions, decorators that do this for you), I've yet to come across an answer which actually explains why this is necessary—which in my opinion is the root of confusion, and leads to unnecessary steps such as needless rebinding and blindly following what others do.
this is dynamic
To understand this specific situation, a brief introduction to how this works. The key thing here is that this is a runtime binding and depends on the current execution context. Hence why it's commonly referred to as "context"—giving information on the current execution context, and why you need to bind is because you loose "context". But let me illustrate the issue with a snippet:
const foobar = {
bar: function () {
return this.foo;
},
foo: 3,
};
console.log(foobar.bar()); // 3, all is good!
In this example, we get 3, as expected. But take this example:
const barFunc = foobar.bar;
console.log(barFunc()); // Uh oh, undefined!
It may be unexpected to find that it logs undefined—where did the 3 go? The answer lies in "context", or how you execute a function. Compare how we call the functions:
// Example 1
foobar.bar();
// Example 2
const barFunc = foobar.bar;
barFunc();
Notice the difference. In the first example, we are specifying exactly where the bar method1 is located—on the foobar object:
foobar.bar();
^^^^^^
But in the second, we store the method into a new variable, and use that variable to call the method, without explicitly stating where the method actually exists, thus losing context:
barFunc(); // Which object is this function coming from?
And therein lies the problem, when you store a method in a variable, the original information about where that method is located (the context in which the method is being executed), is lost. Without this information, at runtime, there is no way for the JavaScript interpreter to bind the correct this—without specific context, this does not work as expected2.
Relating to React
Here's an example of a React component (shortened for brevity) suffering from the this problem:
handleClick() {
this.setState(({ clicks }) => ({ // setState is async, use callback to access previous state
clicks: clicks + 1, // increase by 1
}));
}
render() {
return (
<button onClick={this.handleClick}>{this.state.clicks}</button>
);
}
But why, and how does the previous section relate to this? This is because they suffer from an abstraction of the same problem. If you take a look how React handles event handlers:
// Edited to fit answer, React performs other checks internally
// props is the current React component's props, registrationName is the name of the event handle prop, i.e "onClick"
let listener = props[registrationName];
// Later, listener is called
So, when you do onClick={this.handleClick}, the method this.handleClick is eventually assigned to the variable listener3. But now you see the problem arise—since we've assigned this.handleClick to listener, we no longer specify exactly where handleClick is coming from! From React's point of view, listener is just some function, not attached to any object (or in this case, React component instance). We have lost context and thus the interpreter cannot infer a this value to use inside handleClick.
Why binding works
You might be wondering, if the interpreter decides the this value at runtime, why can I bind the handler so that it does work? This is because you can use Function#bind to guarantee the this value at runtime. This is done by setting an internal this binding property on a function, allowing it to not infer this:
this.handleClick = this.handleClick.bind(this);
When this line is executed, presumably in the constructor, the current this is captured (the React component instance) and set as an internal this binding of a entirely new function, returned from Function#bind. This makes sure that when this is being calculated at runtime, the interpreter will not try to infer anything, but use the provided this value you given it.
Why arrow function properties work
Arrow function class properties currently work through Babel based on the transpilation:
handleClick = () => { /* Can use this just fine here */ }
Becomes:
constructor() {
super();
this.handleClick = () => {}
}
And this works due to the fact arrow functions do not bind their own this, but take the this of their enclosing scope. In this case, the constructor's this, which points to the React component instance—thus giving you the correct this.4
1 I use "method" to refer to a function that is supposed to be bound to an object, and "function" for those not.
2 In the second snippet, undefined is logged instead of 3 because this defaults to the global execution context (window when not in strict mode, or else undefined) when it cannot be determined via specific context. And in the example window.foo does not exist thus yielding undefined.
3 If you go down the rabbit hole of how events in the event queue are executed, invokeGuardedCallback is called on the listener.
4 It's actually a lot more complicated. React internally tries to use Function#apply on listeners for its own use, but this does not work arrow functions as they simply do not bind this. That means, when this inside the arrow function is actually evaluated, the this is resolved up each lexical environment of each execution context of the current code of the module. The execution context which finally resolves to have a this binding is the constructor, which has a this pointing to the current React component instance, allowing it to work.
You can tackle this by three ways
1.Bind the event function in the constructor itself as follows
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {inputContent: 'startValue'}
this.changeContent = this.changeContent.bind(this);
}
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
2.Bind when it is called
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.bind(this)}>Submit</button>
</div>
)
}
}
export default SomeClass
3.By using Arrow functions
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
We need to bind the event function with the component in constructor as follows,
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {inputContent: 'startValue'}
this.changeContent = this.changeContent.bind(this);
}
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
Thanks
My recommendation is use arrow functions as a properties
class SomeClass extends React.Component {
handleClick = () => {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
and do not use arrow functions as
class SomeClass extends React.Component {
handleClick(){
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={()=>{this.handleClick}}></button>
);
}
}
because second approach will generate new function every render call in fact this means new pointer new version of props, than if you will later care about performance you are able use React.PureComponent or in React.Component you can override shouldComponentUpdate(nextProps, nextState) and shallow check when props arrived
You can solve this following these steps
Change sendContent function with
sendContent(e) {
console.log('sending input content '+this.refs.someref.value)
}
Change render function with
<input type="text" ref="someref" value={this.state.inputContent}
onChange={(event)=>this.changeContent(event)} />
<button onClick={(event)=>this.sendContent(event)}>Submit</button>
We have to bind our function with this to get instance of the function in class. Like so in example
<button onClick={this.sendContent.bind(this)}>Submit</button>
This way this.state will be valid object.
if anyone will ever reach this answer,
here is a way to bind all of the functions without needing to bind them manually
in the constructor():
for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {
this[member] = this[member].bind(this)
}
or create this function in a global.jsx file
export function bindAllFunctions({ bindTo: dis }) {
for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(dis))) {
dis[member] = dis[member].bind(dis)
}
}
and in your constructor() call it like:
bindAllFunctions({ bindTo: this })
This issue is happening because this.changeContent and onClick={this.sendContent} are not bound to this of the instance of the component .
There is another solution (In addition to use bind() in the constructor() ) to use the arrow functions of ES6 which share the same lexical scope of the surrounding code and maintain this , so you can change your code in render() to be :
render() {
return (
<input type="text"
onChange={ () => this.changeContent() } />
<button onClick={ () => this.sendContent() }>Submit</button>
)
}
Hello if you want to dont care about binding yourself your function call. You can use 'class-autobind' and import it like that
import autobind from 'class-autobind';
class test extends Component {
constructor(props){
super(props);
autobind(this);
}
Dont write autobind before the super call because it will not work
In case you want to keep the bind in constructor syntax, you can use the proposal-bind-operator and transform your code like follow :
constructor() {
this.changeContent = ::this.changeContent;
}
Instead of :
constructor() {
this.changeContent = this.changeContent.bind(this);
}
much simpler, no need of bind(this) or fatArrow.
this problem happen after react15.0 ,which event handler didn't auto bind to the component. so you must bind this to component manually whenever the event handler will be called.
there are several methods to solve the problem. but you need to know which method is best and why? In general, we recommend that binding your functions in the class constructor or use a arrow function.
// method 1: use a arrow function
class ComponentA extends React.Component {
eventHandler = () => {
console.log(this)
}
render() {
return (
<ChildComponent onClick={this.eventHandler} />
);
}
// method 2: Bind your functions in the class constructor.
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.eventHandler = this.eventHandler.bind(this);
}
render() {
return (
<ChildComponent onClick={this.eventHandler} />
);
}
these two methods will not creates a new function when the component render everytime. so our ChildComponent will not reRender becaue of the new function props change, or may produce the performance problem.
You are using ES6 so functions will not bind to "this" context automatically. You have to manually bind the function to the context.
constructor(props) {
super(props);
this.changeContent = this.changeContent.bind(this);
}
Your functions needs binding in order to play with state or props in event handlers
In ES5, bind your event handler functions only in constructor but don't bind directly in render. If you do binding directly in render then it creates a new function every time your component renders and re-renders. So you should always bind it in constructor
this.sendContent = this.sendContent.bind(this)
In ES6, use arrow functions
When you use arrow functions then you no need to do binding and you can also stay away from scope related issues
sendContent = (event) => {
}
Alexandre Kirszenberg is correct, But another important thing to pay attention to , is where you put your binding. I have been stuck with a situation for days(probably because I'm a beginner), but unlike others, I knew about bind(Which I had applied already) so I just couldn't get my head around why I was still having those errors. It turns out that I had the bind in wrong order.
Another is also perhaps the fact that I was calling the function within "this.state", which was not aware of the bind because it happened to be above the bind line,
Below is what I had(By the way this is my first ever posting, But I thought it was very important, as I couldn't find solution any where else):
constructor(props){
super(props);
productArray=//some array
this.state={
// Create an Array which will hold components to be displayed
proListing:productArray.map(product=>{return(<ProRow dele={this.this.popRow()} prodName={product.name} prodPrice={product.price}/>)})
}
this.popRow=this.popRow.bind(this);//This was the Issue, This line //should be kept above "this.state"
Solution:
Without explicitly binding, bind with the method name you can use fat arrow functions syntax ()=>{} that maintains the context of this.
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {
inputContent: 'startValue'
}
}
sendContent = (e) => {
console.log('sending input content ',this.state.inputContent);
}
changeContent = (e) => {
this.setState({inputContent: e.target.value},()=>{
console.log('STATE:',this.state);
})
}
render() {
return (
<div>
<h4>The input form is here:</h4>
Title:
<input type="text" value={this.state.inputContent}
onChange={this.changeContent} />
<button onClick={this.sendContent}>Submit</button>
</div>
)
}
}
export default SomeClass
Other Solutions:
Bind your functions in the class constructor.
Bind your functions in the JSX Template escaping braces {}
{this.methodName.bind(this)}
bind(this) can fix this issue, and nowadays we can use another 2 ways to achieve this if you don't like using bind .
1) As the traditional way, we can use bind(this) in the constructor, so that when we use the function as JSX callback, the context of this is the class itself.
class App1 extends React.Component {
constructor(props) {
super(props);
// If we comment out the following line,
// we will get run time error said `this` is undefined.
this.changeColor = this.changeColor.bind(this);
}
changeColor(e) {
e.currentTarget.style.backgroundColor = "#00FF00";
console.log(this.props);
}
render() {
return (
<div>
<button onClick={this.changeColor}> button</button>
</div>
);
}
}
2) If we define the function as an attribute/field of the class with arrow function, we don't need to use bind(this) any more.
class App2 extends React.Component {
changeColor = e => {
e.currentTarget.style.backgroundColor = "#00FF00";
console.log(this.props);
};
render() {
return (
<div>
<button onClick={this.changeColor}> button 1</button>
</div>
);
}
}
3) If we use arrow function as JSX callback, we don't need to use bind(this) either. And further more, we can pass in the parameters. Looks good, isn't it? but its drawback is the performance concern, for details please refer ReactJS doco.
class App3 extends React.Component {
changeColor(e, colorHex) {
e.currentTarget.style.backgroundColor = colorHex;
console.log(this.props);
}
render() {
return (
<div>
<button onClick={e => this.changeColor(e, "#ff0000")}> button 1</button>
</div>
);
}
}
And I have created a Codepen to demo these code snippets, hope it helps.

What is the difference between these methods in class

I'm new to react and I can not understand the difference between these two methods in a class
doSomething=()=>{
console.log("Something")
}
and
doSomething() {
console.log("Something")
}
Both looks like they do the same thing
Once again this has been introduced in new ES7 syntax. You can read more about it here
https://www.reactnative.guide/6-conventions-and-code-style/6.4-es7-features.html
Basically in old ES6 we had to write classes and binding methods like this (copied from the documentation)
class SomeComponent extends Component {
_incrementCounter() {
this.setState({count: this.state.count+1})
}
constructor() {
this._incrementCounter = this._incrementCounter.bind(this);
}
...
}
In new ES7 you can simply use arrow function
class SomeComponent extends Component {
_incrementCounter = () => {
this.setState({count: this.state.count+1})
}
...
}
It is up to you what you gonna use. Both ways are ok to use but as you can see ES7 syntax is much shorter and easier to read
doSomething=()=>{
console.log("Something")
}
The above one is using fat arrow functions. You can access this (the class instance) inside this function without binding.
The second one is just defining a function. You will not have access to this here. You cannot use this inside that function. To use this you need to bind the function in constructor or in some other place
Eg;
this.doSomething = this.doSomething.bind(this);
More on this keyword
This is not quite so React specific but it does have implications when passing these functions around to other contexts.
Classes in ES6 don't require binding to allow the use of this within their methods, for example the following is perfectly valid:
class TestClass {
constructor() {
this.variable = 'a variable';
}
method() {
console.log(this.variable)
}
}
const thing = new TestClass();
thing.method(); // will output 'a variable'
The reason you would specifically want to use an arrow function is so you can pass this function down to a component as a prop or use it as part of a button action. Once you have passed the method reference away it no longer has access to this.
class TestComponent extends Component {
constructor() {
this.variable = 'a variable';
}
method() {
console.log(this.variable)
}
render() {
return <AnotherComponent method={this.method} />
}
}
Calling this.method from inside <AnotherComponent> will produce an error. This is where the arrow function comes in.
class TestComponent extends Component {
constructor() {
this.variable = 'a variable';
}
method = () => {
console.log(this.variable)
}
render() {
return <AnotherComponent method={this.method} />
}
}
method now uses an arrow function and 'lexically binds' this which basically means it takes its this from its surrounding context, in this case the class (component) it has been defined in.

someting wrong in react to do list [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 2 years ago.
I am writing a simple component in ES6 (with BabelJS), and functions this.setState is not working.
Typical errors include something like
Cannot read property 'setState' of undefined
or
this.setState is not a function
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
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.
Morhaus is correct, but this can be solved without bind.
You can use an arrow function together with the class properties proposal:
class SomeClass extends React.Component {
changeContent = (e) => {
this.setState({inputContent: e.target.value})
}
render() {
return <input type="text" onChange={this.changeContent} />;
}
}
Because the arrow function is declared in the scope of the constructor, and because arrow functions maintain this from their declaring scope, it all works. The downside here is that these wont be functions on the prototype, they will all be recreated with each component. However, this isn't much of a downside since bind results in the same thing.
This issue is one of the first things most of us experience, when transitioning from the React.createClass() component definition syntax to the ES6 class way of extending React.Component.
It is caused by the this context differences in React.createClass() vs extends React.Component.
Using React.createClass() will automatically bind this context (values) correctly, but that is not the case when using ES6 classes. When doing it the ES6 way (by extending React.Component) the this context is null by default. Properties of the class do not automatically bind to the React class (component) instance.
Approaches to Solve this Issue
I know a total of 4 general approaches.
Bind your functions in the class constructor. Considered by many as a best-practice approach that avoids touching JSX at all and doesn't create a new function on each component re-render.
class SomeClass extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Bind your functions inline. You can still find this approach used here and there in some tutorials / articles / etc, so it's important you're aware of it. It it the same concept like #1, but be aware that binding a function creates a new function per each re-render.
class SomeClass extends React.Component {
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick.bind(this)}></button>
);
}
}
Use a fat arrow function. Until arrow functions, every new function defined its own this value. However, the arrow function does not create its own this context, so this has the original meaning from the React component instance. Therefore, we can:
class SomeClass extends React.Component {
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={ () => this.handleClick() }></button>
);
}
}
or
class SomeClass extends React.Component {
handleClick = () => {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Use utility function library to automatically bind your functions. There are a few utility libraries out there, that automatically does the job for you. Here are some of the popular, just to mention a few:
Autobind Decorator is an NPM package which binds methods of a class to the correct instance of this, even when the methods are detached. The package uses #autobind before methods to bind this to the correct reference to the component's context.
import autobind from 'autobind-decorator';
class SomeClass extends React.Component {
#autobind
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Autobind Decorator is smart enough to let us bind all methods inside a component class at once, just like approach #1.
Class Autobind is another NPM package that is widely used to solve this binding issue. Unlike Autobind Decorator, it does not use of the decorator pattern, but really just uses a function inside your constructor that automatically binds the Component's methods to the correct reference of this.
import autobind from 'class-autobind';
class SomeClass extends React.Component {
constructor() {
autobind(this);
// or if you want to bind only only select functions:
// autobind(this, 'handleClick');
}
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
PS: Other very similar library is React Autobind.
Recommendation
If I were you, I would stick with approach #1. However, as soon as you get a ton of binds in your class constructor, I would recommend you to explore one of the helper libraries mentioned in approach #4.
Other
It's not related to the issue you have, but you shouldn't overuse refs.
Your first inclination may be to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy.
For similar purposes, just like the one you need, using a controlled component is the preferred way. I suggest you to consider using your Component state. So, you can simply access the value like this: this.state.inputContent.
Although the previous answers have provided the basic overview of solutions (i.e. binding, arrow functions, decorators that do this for you), I've yet to come across an answer which actually explains why this is necessary—which in my opinion is the root of confusion, and leads to unnecessary steps such as needless rebinding and blindly following what others do.
this is dynamic
To understand this specific situation, a brief introduction to how this works. The key thing here is that this is a runtime binding and depends on the current execution context. Hence why it's commonly referred to as "context"—giving information on the current execution context, and why you need to bind is because you loose "context". But let me illustrate the issue with a snippet:
const foobar = {
bar: function () {
return this.foo;
},
foo: 3,
};
console.log(foobar.bar()); // 3, all is good!
In this example, we get 3, as expected. But take this example:
const barFunc = foobar.bar;
console.log(barFunc()); // Uh oh, undefined!
It may be unexpected to find that it logs undefined—where did the 3 go? The answer lies in "context", or how you execute a function. Compare how we call the functions:
// Example 1
foobar.bar();
// Example 2
const barFunc = foobar.bar;
barFunc();
Notice the difference. In the first example, we are specifying exactly where the bar method1 is located—on the foobar object:
foobar.bar();
^^^^^^
But in the second, we store the method into a new variable, and use that variable to call the method, without explicitly stating where the method actually exists, thus losing context:
barFunc(); // Which object is this function coming from?
And therein lies the problem, when you store a method in a variable, the original information about where that method is located (the context in which the method is being executed), is lost. Without this information, at runtime, there is no way for the JavaScript interpreter to bind the correct this—without specific context, this does not work as expected2.
Relating to React
Here's an example of a React component (shortened for brevity) suffering from the this problem:
handleClick() {
this.setState(({ clicks }) => ({ // setState is async, use callback to access previous state
clicks: clicks + 1, // increase by 1
}));
}
render() {
return (
<button onClick={this.handleClick}>{this.state.clicks}</button>
);
}
But why, and how does the previous section relate to this? This is because they suffer from an abstraction of the same problem. If you take a look how React handles event handlers:
// Edited to fit answer, React performs other checks internally
// props is the current React component's props, registrationName is the name of the event handle prop, i.e "onClick"
let listener = props[registrationName];
// Later, listener is called
So, when you do onClick={this.handleClick}, the method this.handleClick is eventually assigned to the variable listener3. But now you see the problem arise—since we've assigned this.handleClick to listener, we no longer specify exactly where handleClick is coming from! From React's point of view, listener is just some function, not attached to any object (or in this case, React component instance). We have lost context and thus the interpreter cannot infer a this value to use inside handleClick.
Why binding works
You might be wondering, if the interpreter decides the this value at runtime, why can I bind the handler so that it does work? This is because you can use Function#bind to guarantee the this value at runtime. This is done by setting an internal this binding property on a function, allowing it to not infer this:
this.handleClick = this.handleClick.bind(this);
When this line is executed, presumably in the constructor, the current this is captured (the React component instance) and set as an internal this binding of a entirely new function, returned from Function#bind. This makes sure that when this is being calculated at runtime, the interpreter will not try to infer anything, but use the provided this value you given it.
Why arrow function properties work
Arrow function class properties currently work through Babel based on the transpilation:
handleClick = () => { /* Can use this just fine here */ }
Becomes:
constructor() {
super();
this.handleClick = () => {}
}
And this works due to the fact arrow functions do not bind their own this, but take the this of their enclosing scope. In this case, the constructor's this, which points to the React component instance—thus giving you the correct this.4
1 I use "method" to refer to a function that is supposed to be bound to an object, and "function" for those not.
2 In the second snippet, undefined is logged instead of 3 because this defaults to the global execution context (window when not in strict mode, or else undefined) when it cannot be determined via specific context. And in the example window.foo does not exist thus yielding undefined.
3 If you go down the rabbit hole of how events in the event queue are executed, invokeGuardedCallback is called on the listener.
4 It's actually a lot more complicated. React internally tries to use Function#apply on listeners for its own use, but this does not work arrow functions as they simply do not bind this. That means, when this inside the arrow function is actually evaluated, the this is resolved up each lexical environment of each execution context of the current code of the module. The execution context which finally resolves to have a this binding is the constructor, which has a this pointing to the current React component instance, allowing it to work.
You can tackle this by three ways
1.Bind the event function in the constructor itself as follows
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {inputContent: 'startValue'}
this.changeContent = this.changeContent.bind(this);
}
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
2.Bind when it is called
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.bind(this)}>Submit</button>
</div>
)
}
}
export default SomeClass
3.By using Arrow functions
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
We need to bind the event function with the component in constructor as follows,
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {inputContent: 'startValue'}
this.changeContent = this.changeContent.bind(this);
}
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
Thanks
My recommendation is use arrow functions as a properties
class SomeClass extends React.Component {
handleClick = () => {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
and do not use arrow functions as
class SomeClass extends React.Component {
handleClick(){
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={()=>{this.handleClick}}></button>
);
}
}
because second approach will generate new function every render call in fact this means new pointer new version of props, than if you will later care about performance you are able use React.PureComponent or in React.Component you can override shouldComponentUpdate(nextProps, nextState) and shallow check when props arrived
You can solve this following these steps
Change sendContent function with
sendContent(e) {
console.log('sending input content '+this.refs.someref.value)
}
Change render function with
<input type="text" ref="someref" value={this.state.inputContent}
onChange={(event)=>this.changeContent(event)} />
<button onClick={(event)=>this.sendContent(event)}>Submit</button>
We have to bind our function with this to get instance of the function in class. Like so in example
<button onClick={this.sendContent.bind(this)}>Submit</button>
This way this.state will be valid object.
if anyone will ever reach this answer,
here is a way to bind all of the functions without needing to bind them manually
in the constructor():
for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {
this[member] = this[member].bind(this)
}
or create this function in a global.jsx file
export function bindAllFunctions({ bindTo: dis }) {
for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(dis))) {
dis[member] = dis[member].bind(dis)
}
}
and in your constructor() call it like:
bindAllFunctions({ bindTo: this })
This issue is happening because this.changeContent and onClick={this.sendContent} are not bound to this of the instance of the component .
There is another solution (In addition to use bind() in the constructor() ) to use the arrow functions of ES6 which share the same lexical scope of the surrounding code and maintain this , so you can change your code in render() to be :
render() {
return (
<input type="text"
onChange={ () => this.changeContent() } />
<button onClick={ () => this.sendContent() }>Submit</button>
)
}
Hello if you want to dont care about binding yourself your function call. You can use 'class-autobind' and import it like that
import autobind from 'class-autobind';
class test extends Component {
constructor(props){
super(props);
autobind(this);
}
Dont write autobind before the super call because it will not work
In case you want to keep the bind in constructor syntax, you can use the proposal-bind-operator and transform your code like follow :
constructor() {
this.changeContent = ::this.changeContent;
}
Instead of :
constructor() {
this.changeContent = this.changeContent.bind(this);
}
much simpler, no need of bind(this) or fatArrow.
this problem happen after react15.0 ,which event handler didn't auto bind to the component. so you must bind this to component manually whenever the event handler will be called.
there are several methods to solve the problem. but you need to know which method is best and why? In general, we recommend that binding your functions in the class constructor or use a arrow function.
// method 1: use a arrow function
class ComponentA extends React.Component {
eventHandler = () => {
console.log(this)
}
render() {
return (
<ChildComponent onClick={this.eventHandler} />
);
}
// method 2: Bind your functions in the class constructor.
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.eventHandler = this.eventHandler.bind(this);
}
render() {
return (
<ChildComponent onClick={this.eventHandler} />
);
}
these two methods will not creates a new function when the component render everytime. so our ChildComponent will not reRender becaue of the new function props change, or may produce the performance problem.
You are using ES6 so functions will not bind to "this" context automatically. You have to manually bind the function to the context.
constructor(props) {
super(props);
this.changeContent = this.changeContent.bind(this);
}
Your functions needs binding in order to play with state or props in event handlers
In ES5, bind your event handler functions only in constructor but don't bind directly in render. If you do binding directly in render then it creates a new function every time your component renders and re-renders. So you should always bind it in constructor
this.sendContent = this.sendContent.bind(this)
In ES6, use arrow functions
When you use arrow functions then you no need to do binding and you can also stay away from scope related issues
sendContent = (event) => {
}
Alexandre Kirszenberg is correct, But another important thing to pay attention to , is where you put your binding. I have been stuck with a situation for days(probably because I'm a beginner), but unlike others, I knew about bind(Which I had applied already) so I just couldn't get my head around why I was still having those errors. It turns out that I had the bind in wrong order.
Another is also perhaps the fact that I was calling the function within "this.state", which was not aware of the bind because it happened to be above the bind line,
Below is what I had(By the way this is my first ever posting, But I thought it was very important, as I couldn't find solution any where else):
constructor(props){
super(props);
productArray=//some array
this.state={
// Create an Array which will hold components to be displayed
proListing:productArray.map(product=>{return(<ProRow dele={this.this.popRow()} prodName={product.name} prodPrice={product.price}/>)})
}
this.popRow=this.popRow.bind(this);//This was the Issue, This line //should be kept above "this.state"
Solution:
Without explicitly binding, bind with the method name you can use fat arrow functions syntax ()=>{} that maintains the context of this.
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {
inputContent: 'startValue'
}
}
sendContent = (e) => {
console.log('sending input content ',this.state.inputContent);
}
changeContent = (e) => {
this.setState({inputContent: e.target.value},()=>{
console.log('STATE:',this.state);
})
}
render() {
return (
<div>
<h4>The input form is here:</h4>
Title:
<input type="text" value={this.state.inputContent}
onChange={this.changeContent} />
<button onClick={this.sendContent}>Submit</button>
</div>
)
}
}
export default SomeClass
Other Solutions:
Bind your functions in the class constructor.
Bind your functions in the JSX Template escaping braces {}
{this.methodName.bind(this)}
bind(this) can fix this issue, and nowadays we can use another 2 ways to achieve this if you don't like using bind .
1) As the traditional way, we can use bind(this) in the constructor, so that when we use the function as JSX callback, the context of this is the class itself.
class App1 extends React.Component {
constructor(props) {
super(props);
// If we comment out the following line,
// we will get run time error said `this` is undefined.
this.changeColor = this.changeColor.bind(this);
}
changeColor(e) {
e.currentTarget.style.backgroundColor = "#00FF00";
console.log(this.props);
}
render() {
return (
<div>
<button onClick={this.changeColor}> button</button>
</div>
);
}
}
2) If we define the function as an attribute/field of the class with arrow function, we don't need to use bind(this) any more.
class App2 extends React.Component {
changeColor = e => {
e.currentTarget.style.backgroundColor = "#00FF00";
console.log(this.props);
};
render() {
return (
<div>
<button onClick={this.changeColor}> button 1</button>
</div>
);
}
}
3) If we use arrow function as JSX callback, we don't need to use bind(this) either. And further more, we can pass in the parameters. Looks good, isn't it? but its drawback is the performance concern, for details please refer ReactJS doco.
class App3 extends React.Component {
changeColor(e, colorHex) {
e.currentTarget.style.backgroundColor = colorHex;
console.log(this.props);
}
render() {
return (
<div>
<button onClick={e => this.changeColor(e, "#ff0000")}> button 1</button>
</div>
);
}
}
And I have created a Codepen to demo these code snippets, hope it helps.

cannot read property 'props' of undefined, React-Redux [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 2 years ago.
I am writing a simple component in ES6 (with BabelJS), and functions this.setState is not working.
Typical errors include something like
Cannot read property 'setState' of undefined
or
this.setState is not a function
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
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.
Morhaus is correct, but this can be solved without bind.
You can use an arrow function together with the class properties proposal:
class SomeClass extends React.Component {
changeContent = (e) => {
this.setState({inputContent: e.target.value})
}
render() {
return <input type="text" onChange={this.changeContent} />;
}
}
Because the arrow function is declared in the scope of the constructor, and because arrow functions maintain this from their declaring scope, it all works. The downside here is that these wont be functions on the prototype, they will all be recreated with each component. However, this isn't much of a downside since bind results in the same thing.
This issue is one of the first things most of us experience, when transitioning from the React.createClass() component definition syntax to the ES6 class way of extending React.Component.
It is caused by the this context differences in React.createClass() vs extends React.Component.
Using React.createClass() will automatically bind this context (values) correctly, but that is not the case when using ES6 classes. When doing it the ES6 way (by extending React.Component) the this context is null by default. Properties of the class do not automatically bind to the React class (component) instance.
Approaches to Solve this Issue
I know a total of 4 general approaches.
Bind your functions in the class constructor. Considered by many as a best-practice approach that avoids touching JSX at all and doesn't create a new function on each component re-render.
class SomeClass extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Bind your functions inline. You can still find this approach used here and there in some tutorials / articles / etc, so it's important you're aware of it. It it the same concept like #1, but be aware that binding a function creates a new function per each re-render.
class SomeClass extends React.Component {
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick.bind(this)}></button>
);
}
}
Use a fat arrow function. Until arrow functions, every new function defined its own this value. However, the arrow function does not create its own this context, so this has the original meaning from the React component instance. Therefore, we can:
class SomeClass extends React.Component {
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={ () => this.handleClick() }></button>
);
}
}
or
class SomeClass extends React.Component {
handleClick = () => {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Use utility function library to automatically bind your functions. There are a few utility libraries out there, that automatically does the job for you. Here are some of the popular, just to mention a few:
Autobind Decorator is an NPM package which binds methods of a class to the correct instance of this, even when the methods are detached. The package uses #autobind before methods to bind this to the correct reference to the component's context.
import autobind from 'autobind-decorator';
class SomeClass extends React.Component {
#autobind
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
Autobind Decorator is smart enough to let us bind all methods inside a component class at once, just like approach #1.
Class Autobind is another NPM package that is widely used to solve this binding issue. Unlike Autobind Decorator, it does not use of the decorator pattern, but really just uses a function inside your constructor that automatically binds the Component's methods to the correct reference of this.
import autobind from 'class-autobind';
class SomeClass extends React.Component {
constructor() {
autobind(this);
// or if you want to bind only only select functions:
// autobind(this, 'handleClick');
}
handleClick() {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
PS: Other very similar library is React Autobind.
Recommendation
If I were you, I would stick with approach #1. However, as soon as you get a ton of binds in your class constructor, I would recommend you to explore one of the helper libraries mentioned in approach #4.
Other
It's not related to the issue you have, but you shouldn't overuse refs.
Your first inclination may be to use refs to "make things happen" in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy.
For similar purposes, just like the one you need, using a controlled component is the preferred way. I suggest you to consider using your Component state. So, you can simply access the value like this: this.state.inputContent.
Although the previous answers have provided the basic overview of solutions (i.e. binding, arrow functions, decorators that do this for you), I've yet to come across an answer which actually explains why this is necessary—which in my opinion is the root of confusion, and leads to unnecessary steps such as needless rebinding and blindly following what others do.
this is dynamic
To understand this specific situation, a brief introduction to how this works. The key thing here is that this is a runtime binding and depends on the current execution context. Hence why it's commonly referred to as "context"—giving information on the current execution context, and why you need to bind is because you loose "context". But let me illustrate the issue with a snippet:
const foobar = {
bar: function () {
return this.foo;
},
foo: 3,
};
console.log(foobar.bar()); // 3, all is good!
In this example, we get 3, as expected. But take this example:
const barFunc = foobar.bar;
console.log(barFunc()); // Uh oh, undefined!
It may be unexpected to find that it logs undefined—where did the 3 go? The answer lies in "context", or how you execute a function. Compare how we call the functions:
// Example 1
foobar.bar();
// Example 2
const barFunc = foobar.bar;
barFunc();
Notice the difference. In the first example, we are specifying exactly where the bar method1 is located—on the foobar object:
foobar.bar();
^^^^^^
But in the second, we store the method into a new variable, and use that variable to call the method, without explicitly stating where the method actually exists, thus losing context:
barFunc(); // Which object is this function coming from?
And therein lies the problem, when you store a method in a variable, the original information about where that method is located (the context in which the method is being executed), is lost. Without this information, at runtime, there is no way for the JavaScript interpreter to bind the correct this—without specific context, this does not work as expected2.
Relating to React
Here's an example of a React component (shortened for brevity) suffering from the this problem:
handleClick() {
this.setState(({ clicks }) => ({ // setState is async, use callback to access previous state
clicks: clicks + 1, // increase by 1
}));
}
render() {
return (
<button onClick={this.handleClick}>{this.state.clicks}</button>
);
}
But why, and how does the previous section relate to this? This is because they suffer from an abstraction of the same problem. If you take a look how React handles event handlers:
// Edited to fit answer, React performs other checks internally
// props is the current React component's props, registrationName is the name of the event handle prop, i.e "onClick"
let listener = props[registrationName];
// Later, listener is called
So, when you do onClick={this.handleClick}, the method this.handleClick is eventually assigned to the variable listener3. But now you see the problem arise—since we've assigned this.handleClick to listener, we no longer specify exactly where handleClick is coming from! From React's point of view, listener is just some function, not attached to any object (or in this case, React component instance). We have lost context and thus the interpreter cannot infer a this value to use inside handleClick.
Why binding works
You might be wondering, if the interpreter decides the this value at runtime, why can I bind the handler so that it does work? This is because you can use Function#bind to guarantee the this value at runtime. This is done by setting an internal this binding property on a function, allowing it to not infer this:
this.handleClick = this.handleClick.bind(this);
When this line is executed, presumably in the constructor, the current this is captured (the React component instance) and set as an internal this binding of a entirely new function, returned from Function#bind. This makes sure that when this is being calculated at runtime, the interpreter will not try to infer anything, but use the provided this value you given it.
Why arrow function properties work
Arrow function class properties currently work through Babel based on the transpilation:
handleClick = () => { /* Can use this just fine here */ }
Becomes:
constructor() {
super();
this.handleClick = () => {}
}
And this works due to the fact arrow functions do not bind their own this, but take the this of their enclosing scope. In this case, the constructor's this, which points to the React component instance—thus giving you the correct this.4
1 I use "method" to refer to a function that is supposed to be bound to an object, and "function" for those not.
2 In the second snippet, undefined is logged instead of 3 because this defaults to the global execution context (window when not in strict mode, or else undefined) when it cannot be determined via specific context. And in the example window.foo does not exist thus yielding undefined.
3 If you go down the rabbit hole of how events in the event queue are executed, invokeGuardedCallback is called on the listener.
4 It's actually a lot more complicated. React internally tries to use Function#apply on listeners for its own use, but this does not work arrow functions as they simply do not bind this. That means, when this inside the arrow function is actually evaluated, the this is resolved up each lexical environment of each execution context of the current code of the module. The execution context which finally resolves to have a this binding is the constructor, which has a this pointing to the current React component instance, allowing it to work.
You can tackle this by three ways
1.Bind the event function in the constructor itself as follows
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {inputContent: 'startValue'}
this.changeContent = this.changeContent.bind(this);
}
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
2.Bind when it is called
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.bind(this)}>Submit</button>
</div>
)
}
}
export default SomeClass
3.By using Arrow functions
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
We need to bind the event function with the component in constructor as follows,
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {inputContent: 'startValue'}
this.changeContent = this.changeContent.bind(this);
}
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
Thanks
My recommendation is use arrow functions as a properties
class SomeClass extends React.Component {
handleClick = () => {
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={this.handleClick}></button>
);
}
}
and do not use arrow functions as
class SomeClass extends React.Component {
handleClick(){
console.log(this); // the React Component instance
}
render() {
return (
<button onClick={()=>{this.handleClick}}></button>
);
}
}
because second approach will generate new function every render call in fact this means new pointer new version of props, than if you will later care about performance you are able use React.PureComponent or in React.Component you can override shouldComponentUpdate(nextProps, nextState) and shallow check when props arrived
You can solve this following these steps
Change sendContent function with
sendContent(e) {
console.log('sending input content '+this.refs.someref.value)
}
Change render function with
<input type="text" ref="someref" value={this.state.inputContent}
onChange={(event)=>this.changeContent(event)} />
<button onClick={(event)=>this.sendContent(event)}>Submit</button>
We have to bind our function with this to get instance of the function in class. Like so in example
<button onClick={this.sendContent.bind(this)}>Submit</button>
This way this.state will be valid object.
if anyone will ever reach this answer,
here is a way to bind all of the functions without needing to bind them manually
in the constructor():
for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {
this[member] = this[member].bind(this)
}
or create this function in a global.jsx file
export function bindAllFunctions({ bindTo: dis }) {
for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(dis))) {
dis[member] = dis[member].bind(dis)
}
}
and in your constructor() call it like:
bindAllFunctions({ bindTo: this })
This issue is happening because this.changeContent and onClick={this.sendContent} are not bound to this of the instance of the component .
There is another solution (In addition to use bind() in the constructor() ) to use the arrow functions of ES6 which share the same lexical scope of the surrounding code and maintain this , so you can change your code in render() to be :
render() {
return (
<input type="text"
onChange={ () => this.changeContent() } />
<button onClick={ () => this.sendContent() }>Submit</button>
)
}
Hello if you want to dont care about binding yourself your function call. You can use 'class-autobind' and import it like that
import autobind from 'class-autobind';
class test extends Component {
constructor(props){
super(props);
autobind(this);
}
Dont write autobind before the super call because it will not work
In case you want to keep the bind in constructor syntax, you can use the proposal-bind-operator and transform your code like follow :
constructor() {
this.changeContent = ::this.changeContent;
}
Instead of :
constructor() {
this.changeContent = this.changeContent.bind(this);
}
much simpler, no need of bind(this) or fatArrow.
this problem happen after react15.0 ,which event handler didn't auto bind to the component. so you must bind this to component manually whenever the event handler will be called.
there are several methods to solve the problem. but you need to know which method is best and why? In general, we recommend that binding your functions in the class constructor or use a arrow function.
// method 1: use a arrow function
class ComponentA extends React.Component {
eventHandler = () => {
console.log(this)
}
render() {
return (
<ChildComponent onClick={this.eventHandler} />
);
}
// method 2: Bind your functions in the class constructor.
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.eventHandler = this.eventHandler.bind(this);
}
render() {
return (
<ChildComponent onClick={this.eventHandler} />
);
}
these two methods will not creates a new function when the component render everytime. so our ChildComponent will not reRender becaue of the new function props change, or may produce the performance problem.
You are using ES6 so functions will not bind to "this" context automatically. You have to manually bind the function to the context.
constructor(props) {
super(props);
this.changeContent = this.changeContent.bind(this);
}
Your functions needs binding in order to play with state or props in event handlers
In ES5, bind your event handler functions only in constructor but don't bind directly in render. If you do binding directly in render then it creates a new function every time your component renders and re-renders. So you should always bind it in constructor
this.sendContent = this.sendContent.bind(this)
In ES6, use arrow functions
When you use arrow functions then you no need to do binding and you can also stay away from scope related issues
sendContent = (event) => {
}
Alexandre Kirszenberg is correct, But another important thing to pay attention to , is where you put your binding. I have been stuck with a situation for days(probably because I'm a beginner), but unlike others, I knew about bind(Which I had applied already) so I just couldn't get my head around why I was still having those errors. It turns out that I had the bind in wrong order.
Another is also perhaps the fact that I was calling the function within "this.state", which was not aware of the bind because it happened to be above the bind line,
Below is what I had(By the way this is my first ever posting, But I thought it was very important, as I couldn't find solution any where else):
constructor(props){
super(props);
productArray=//some array
this.state={
// Create an Array which will hold components to be displayed
proListing:productArray.map(product=>{return(<ProRow dele={this.this.popRow()} prodName={product.name} prodPrice={product.price}/>)})
}
this.popRow=this.popRow.bind(this);//This was the Issue, This line //should be kept above "this.state"
Solution:
Without explicitly binding, bind with the method name you can use fat arrow functions syntax ()=>{} that maintains the context of this.
import React from 'react'
class SomeClass extends React.Component {
constructor(props) {
super(props)
this.state = {
inputContent: 'startValue'
}
}
sendContent = (e) => {
console.log('sending input content ',this.state.inputContent);
}
changeContent = (e) => {
this.setState({inputContent: e.target.value},()=>{
console.log('STATE:',this.state);
})
}
render() {
return (
<div>
<h4>The input form is here:</h4>
Title:
<input type="text" value={this.state.inputContent}
onChange={this.changeContent} />
<button onClick={this.sendContent}>Submit</button>
</div>
)
}
}
export default SomeClass
Other Solutions:
Bind your functions in the class constructor.
Bind your functions in the JSX Template escaping braces {}
{this.methodName.bind(this)}
bind(this) can fix this issue, and nowadays we can use another 2 ways to achieve this if you don't like using bind .
1) As the traditional way, we can use bind(this) in the constructor, so that when we use the function as JSX callback, the context of this is the class itself.
class App1 extends React.Component {
constructor(props) {
super(props);
// If we comment out the following line,
// we will get run time error said `this` is undefined.
this.changeColor = this.changeColor.bind(this);
}
changeColor(e) {
e.currentTarget.style.backgroundColor = "#00FF00";
console.log(this.props);
}
render() {
return (
<div>
<button onClick={this.changeColor}> button</button>
</div>
);
}
}
2) If we define the function as an attribute/field of the class with arrow function, we don't need to use bind(this) any more.
class App2 extends React.Component {
changeColor = e => {
e.currentTarget.style.backgroundColor = "#00FF00";
console.log(this.props);
};
render() {
return (
<div>
<button onClick={this.changeColor}> button 1</button>
</div>
);
}
}
3) If we use arrow function as JSX callback, we don't need to use bind(this) either. And further more, we can pass in the parameters. Looks good, isn't it? but its drawback is the performance concern, for details please refer ReactJS doco.
class App3 extends React.Component {
changeColor(e, colorHex) {
e.currentTarget.style.backgroundColor = colorHex;
console.log(this.props);
}
render() {
return (
<div>
<button onClick={e => this.changeColor(e, "#ff0000")}> button 1</button>
</div>
);
}
}
And I have created a Codepen to demo these code snippets, hope it helps.

How to properly use arrows for ES6 React class functions? [duplicate]

I'm new to using ES6 classes with React, previously I've been binding my methods to the current object (show in first example), but does ES6 allow me to permanently bind a class function to a class instance with arrows? (Useful when passing as a callback function.) I get errors when I try to use them as you can with CoffeeScript:
class SomeClass extends React.Component {
// Instead of this
constructor(){
this.handleInputChange = this.handleInputChange.bind(this)
}
// Can I somehow do this? Am i just getting the syntax wrong?
handleInputChange (val) => {
console.log('selectionMade: ', val);
}
So that if I were to pass SomeClass.handleInputChange to, for instance setTimeout, it would be scoped to the class instance, and not the window object.
Your syntax is slightly off, just missing an equals sign after the property name.
class SomeClass extends React.Component {
handleInputChange = (val) => {
console.log('selectionMade: ', val);
}
}
This is an experimental feature. You will need to enable experimental features in Babel to get this to compile. Here is a demo with experimental enabled.
To use experimental features in babel you can install the relevant plugin from here. For this specific feature, you need the transform-class-properties plugin:
{
"plugins": [
"transform-class-properties"
]
}
You can read more about the proposal for Class Fields and Static Properties here
No, if you want to create bound, instance-specific methods you will have to do that in the constructor. However, you can use arrow functions for that, instead of using .bind on a prototype method:
class SomeClass extends React.Component {
constructor() {
super();
this.handleInputChange = (val) => {
console.log('selectionMade: ', val, this);
};
…
}
}
There is an proposal which might allow you to omit the constructor() and directly put the assignment in the class scope with the same functionality, but I wouldn't recommend to use that as it's highly experimental.
Alternatively, you can always use .bind, which allows you to declare the method on the prototype and then bind it to the instance in the constructor. This approach has greater flexibility as it allows modifying the method from the outside of your class.
class SomeClass extends React.Component {
constructor() {
super();
this.handleInputChange = this.handleInputChange.bind(this);
…
}
handleInputChange(val) {
console.log('selectionMade: ', val, this);
}
}
You are using arrow function and also binding it in constructor. So you no need to do binding when you use arrow functions
class SomeClass extends React.Component {
handleInputChange = (val) => {
console.log('selectionMade: ', val);
}
}
OR you need to bind a function only in constructor when you use normal function like below
class SomeClass extends React.Component {
constructor(props){
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(val){
console.log('selectionMade: ', val);
}
}
Also binding a function directly in render is not recommended. It should always be in constructor
I know this question has been sufficiently answered, but I just have a small contribution to make (for those who don't want to use the experimental feature). Because of the problem of having to bind multiple function binds in the constructor and making it look messy, I came up with a utility method that once bound and called in the constructor, does all the necessary method bindings for you automatically.
Assume I have this class with the constructor:
//src/components/PetEditor.jsx
import React from 'react';
class PetEditor extends React.Component {
constructor(props){
super(props);
this.state = props.currentPet || {tags:[], photoUrls: []};
this.tagInput = null;
this.htmlNode = null;
this.removeTag = this.removeTag.bind(this);
this.handleChange = this.handleChange.bind(this);
this.modifyState = this.modifyState.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.addTag = this.addTag.bind(this);
this.removeTag = this.removeTag.bind(this);
this.savePet = this.savePet.bind(this);
this.addPhotoInput = this.addPhotoInput.bind(this);
this.handleSelect = this.handleSelect.bind(this);
}
// ... actual method declarations omitted
}
It looks messy, doesn't it?
Now I created this utility method
//src/utils/index.js
/**
* NB: to use this method, you need to bind it to the object instance calling it
*/
export function bindMethodsToSelf(objClass, otherMethodsToIgnore=[]){
const self = this;
Object.getOwnPropertyNames(objClass.prototype)
.forEach(method => {
//skip constructor, render and any overrides of lifecycle methods
if(method.startsWith('component')
|| method==='constructor'
|| method==='render') return;
//any other methods you don't want bound to self
if(otherMethodsToIgnore.indexOf(method)>-1) return;
//bind all other methods to class instance
self[method] = self[method].bind(self);
});
}
All I now need to do is import that utility, and add a call to my constructor, and I don't need to bind each new method in the constructor anymore.
New constructor now looks clean, like this:
//src/components/PetEditor.jsx
import React from 'react';
import { bindMethodsToSelf } from '../utils';
class PetEditor extends React.Component {
constructor(props){
super(props);
this.state = props.currentPet || {tags:[], photoUrls: []};
this.tagInput = null;
this.htmlNode = null;
bindMethodsToSelf.bind(this)(PetEditor);
}
// ...
}

Resources