React: 'this' becomes undefined when called from onClick inside a class that extends React.Component

Created on 2 Oct 2015  路  4Comments  路  Source: facebook/react

I have something similar to this code snippet:

class MyButton extends Component {

    state = { tapped: false }
    tap() {
          this.setState({ tapped: true });  // --> 'this' here is undefined 
    }
    render() {
        return (
             <button onClick={ this.tap }>TAP ME</button>
        )
    }
}

As the comment above specifies, when the tap() method got called from the button's onclick, I got an error that basically told me that 'this' is undefined.

This error will be gone if I declare this class using React.createClass. Is this intentional? Thank you in advance!

Most helpful comment

React.createClass auto bind this for you behind the scene.

In ES6 classes, you should bind this yourself: <button onClick={this.tap.bind(this)}>

All 4 comments

React.createClass auto bind this for you behind the scene.

In ES6 classes, you should bind this yourself: <button onClick={this.tap.bind(this)}>

I see, thank you so much!

Just for info, it can also be solved as below,

class MyButton extends Component {

    state = { tapped: false }
    tap = (e) => {
          this.setState({ tapped: true });
    }
    render() {
        return (
             <button onClick={ this.tap }>TAP ME</button>
        )
    }
}

In my case, for a stateless component that received the ref with forwardRef, I had to do what it is said here https://itnext.io/reusing-the-ref-from-forwardref-with-react-hooks-4ce9df693dd

From this (onClick doesn't have access to the equivalent of 'this')

const Com = forwardRef((props, ref) => {
  return <input ref={ref} onClick={() => {console.log(ref.current} } />
})

To this (it works)

const useCombinedRefs = (...refs) => {
  const targetRef = React.useRef()

  useEffect(() => {
    refs.forEach(ref => {
      if (!ref) return

      if (typeof ref === 'function') ref(targetRef.current)
      else ref.current = targetRef.current
    })
  }, [refs])

  return targetRef
}

const Com = forwardRef((props, ref) => {
  const innerRef = useRef()
  const combinedRef = useCombinedRefs(ref, innerRef)

  return <input ref={combinedRef } onClick={() => {console.log(combinedRef .current} } />
})
Was this page helpful?
0 / 5 - 0 ratings