4

I have a function handleInputChange that I want to write once (DRY principle), but apply it to many of my React classes. However, binding to this in the constructor doesn't work.

handleInputChange = (key, value) => {this.setState(key: value)}
class Login extends Component {
 constructor(props) {
 super(props);
 this.state = {
 loginBox: {
 username: "",
 password: ""}
 }
 this.handleInputChange = handleInputChange.bind(this) // DOESN't WORK
}}

Why does the above method not work? The error I get is:

Uncaught TypeError: Cannot read property 'setState' of undefined

I am currently using this function wrapper workaround, but I'd rather bind the function directly.

handleInputChange = (_this) => () => (key, value) => {_this.setState(key: value)}
class Login extends Component {
 ...
 this.handleInputChange = (key, value) => handleInputChange(this)(key, value)
asked Oct 16, 2019 at 23:08

3 Answers 3

3

You can't bind this in arrow functions. this falls through to the parent scope.

You could make it a non-arrow function:

function handleInputChange(key, value) { this.setState(key: value) }

But I'd suggest making it a method on the class. Defining a function that references this is tricky to read, because you never know what this will be when it executes, making it hard to read the function at a glance.

answered Oct 16, 2019 at 23:23

Comments

1

arrow functions do not have their own this, if you use call([this obj], args), apply([this obj], args), Any "this" argument is ignored. I guess the same applies to bind(obj), it doesn't bind this to the object you provided because it doesn't have its own this.

this inside arrow functions is decided by this in the lexical scope where the arrow function is defined. If you define your handleInputChange in global scope, this inside is the global object(in browser it's window), that's the reason you get the error.

If you want to use bind, you can define the function like this

function handleInputChange(key, value) { this.setState(key: value) }

When you call bind, this will be set to the object you provided in bind.

answered Oct 16, 2019 at 23:33

Comments

0

Since you are calling this function inside the class, it's better to define it as a method within the class instead of defining it outside, so that the this issue is less of a, well, issue.

Inside the class makes it fairly straightforward:

constructor(props) {
this.handleInputChange = this.handleInputChange.bind(this)
}
handleInputChange() {
 //Code
}

Or if you want to avoid having to do the messy bind method, you can use an arrow function for the method:

handleInputChange = () => {
 console.log('This is: ', this);
}
...
render() {
 return(
 <button onClick={this.handleInputChange}>Click</button>
 );
}

Reference react handling events

answered Oct 17, 2019 at 1:12

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.