question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot set property with ref callback

See original GitHub issue

I am trying to set a ref attribute using a class method:

export default class Foo extends Component {
    handleClick (event) {
      console.log(this.foobar);
    }

    setRef (ref) { // Using this syntax works in the REPL: setRef = (ref) => {  
      console.log(ref); // <input>
      console.log(this); // undefined
      this.foobar = ref; // error
      return ref;
    }

    render() {
        return (
            <div>
                <input ref={this.setRef} />
                <button onClick={this.handleClick}>click me</button>
            </div>
        );
    }
}

As already commented in the code snippet, this is undefined in setRef() and thus, setting this.foobar fails with a Cannot set property ‘foobar’ of undefined error…

What am I missing here?

Note: I am using ECMAScript 6 via Babel. In the Preact REPL I can use the alternative syntax as commented (fat arrow) to make the code working. Could this be a Babel issue?

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
developitcommented, May 15, 2016

Hi @p3k: the reason setRef errors here is because without the fat arrow syntax, the method is not bound to the class instance. When preact calls your setRef function, it does not invoke it with context, so the value of this is always undefined. Using the fat arrow syntax or a locally defined function provides the desired value for this.

If you’re getting an error when trying to transpile the fat arrow method syntax in Babel, make sure you have installed and enabled the babel-plugin-transform-class-properties plugin, or the stage-0 preset which includes it.

Other options for statically binding class methods would include using a @bind decorator (like decko’s) or binding manually in a constructor:

export default class Foo extends Component {
    constructor(props, context) {
        super(props, context);
        this.setRef = this.setRef.bind(this);
    }
    setRef (ref) {
      this.foobar = ref;
    }
}

However, it’s worth noting the resulting output simplicity when using the fat arrow technique: https://goo.gl/TQJ44T

I had previously been promoting the use of @bind and similar solutions, but I think the ES5 output of the fat arrow property methods is quite pleasant.

0reactions
developitcommented, May 20, 2016

@leonid-bauxy the implementation of ref is different from Events. It’s always invoked on the component itself (implementation). Your other PR is definitely interesting though, I think we need to drop the .call there as you recommended.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React Ref - Cannot set property 'innerHTML' of null
I have tried both the standard React.createRef() and callback style ref but the current value of all the refs is returning null. What...
Read more >
Refs and the DOM
If the ref callback is defined as an inline function, it will get called twice during updates, first with null and then again...
Read more >
React Callback Refs — a Complex Case | by E.Y. - Medium
In my last article, I discussed about accessing DOM/React element through its ref API. Today we are going to look at an advanced...
Read more >
Avoiding useEffect with callback refs - TkDodo's blog
ref is a reserved property on build-in primitives, where React will store the DOM node after it was rendered. It will be set...
Read more >
Understanding Callback Refs
The callback function passed to the ref attribute executes immediately upon the component mounting. · The stored element is directly accessible ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found