7

I got the following component written in typescript. (type definitions from definitelytyped.org). I got the onWheel event bound to a function. But when ever it is fired this is undefined, so how am I supposed to access the referenced element this.div and if I would want/need to change the state how should do that?

import React = require('react');

interface fooProps {
    src: string;
}

class foo extends React.Component<fooProps, {}>
{
    private div: HTMLDivElement;

    public onWheel(e: React.WheelEvent): void {
        e.preventDefault();
        e.stopPropagation();

        //Do stuff with the div, but 'this' is undefined!!
        this.div;
    }
    public render(): JSX.Element {
                return (
            <div ref={(ref) => this.div = ref} onWheel= { this.onWheel} >
                <img src={ this.props.src } />
                </div >)
    }
}

4 Answers 4

7

Don't know about Typescript, but I'm guessing it's the same thing as when creating components using the similar ES2015 syntax which will need a constructor, and function binding to make a reference to this.onWheel work.

So in ES2015,

class foo extends React.Component {
  constructor(props) {
    super(props);
    // Magic happens here:
    this.onWheel = this.onWheel.bind(this)
    // Now each instance of foo can use this.onWheel
  }

  onWheel () {
    ....
  }

  render (){
    ....
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

This is actually a preferred way of binding event handlers in React components to the answer by Qwertiy. If you do the binding inside the constructor like in the snippet above, that means you only create a copy of the function once whereas if you do it inside of the render method the function will get re-created every time React re-renders the component. Worth bearing it in mind when performance is a major consideration.
But then how is the event bound? I still got to put onWheel={this.onWheel} in the render method right?
Just do it the way you already do. It should work fine. My code example didn't have onWheel(e: React.WheelEvent), because the point was what's going on in the constructor.
5

Another solution if you don't want to bind each function in the constructor is to use lambdas:

class foo extends React.Component {
  constructor(props) {
    super(props);
  }

  // The lambda creates a lexical scope so it's autobound
  onWheel = () => {
    ....
  }

  render () {
    ....
  }
}

You can read more here.

1 Comment

Beat me to the punch.
2
onWheel= { this.onWheel}
onWheel={this.onWheel.bind(this)}

1 Comment

You can also write it in lambda form onWheel={e => this.onWheel(e)} it will call the appropriate method using closures
1

The simple thing would be converting it into an arrow function which binds automatically:

 public onWheel = (e: React.WheelEvent): void => {
    e.preventDefault();
    e.stopPropagation();

    //Do stuff with the div, and yes you can work with 'this' in this function
    this.div;
}

Comments

Your Answer

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.