简体   繁体   中英

How to bind a function's “this” to a class (React Component)

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)

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.

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 .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM