The recommended pattern is for callback refs to have minimal side-effects, and to use React…
Alex Krolick

Alex, you’re right that I’m doing a little more than is ideal in a ref callback. But the way callback refs are implemented, you have to have some code complexity somewhere if you need to hold onto a reference to a DOM element, and do asynchronous things with that reference outside the React render loop.

You can’t do the thing that’s in the React docs unless you constantly check for nulleverywhere you use that reference.

ref={(input) => { this.textInput = input; }}

Doing the above results in this.textInput getting set to null each time render() is called, then getting set again to the DOM element object.

The use case I’m writing about is that I need to get a reference to the DOM object when the DOM element is first created during a render, which in my case is not when the component is mounted. The render logic conditionally creates the DOM element depending on application state. Once I have that reference, I need to be able to call methods that use the DOM element asynchronously, in timer-based callbacks. (I’m getting data out of a canvas, or manipulating the state of a video element, for example.)

With the approach I outlined in the article, all of the setup logic is in the ref callback, rather than split up between the ref callback and componentDidUpdate. That seems like a useful simplification, to me. Thoug of course there are other good ways to write this code.