React and autofocus

By  on  

While I love ReactJS, I can say that I sometimes find interactions that were easy during the pre-ReactJS are annoyingly difficult or at least "indirect".  One example is properly ensuring that a given <input> element gets focused when a button in a different component is clicked; in the old days, it was three lines of code, but with React it can be more.

Let's have a look at a few strategies for properly focusing on <input> elements with ReactJS.

autofocus

The autofocus attribute is honored in ReactJS but only when the <input> element is re-rendered with React:

<input type="text" autofocus="true" />

autofocus is easy to use but only works when the <input> is initially rendered; since React intelligently only re-renders elements that have changed, the autofocus attribute isn't reliable in all cases.

componentDidUpdate with ref

Since we can't rely solely on the autofocus attribute, we can use componentDidUpdate to complete the focus:

class Expressions extends Component {

  _input: ?HTMLInputElement;

  // ....

  componentDidUpdate(prevProps, prevState) {
    this._input.focus();
  }

  render() {
      return (
        <div className={this.state.focused ? "focused": ""}>
            <input
              autofocus="true"
              ref={c => (this._input = c)}
            />
        </div>
      );
    }
  }
}

componentDidUpdate fires after the component is updated, so any change to the parent component would trigger this method and your <input> would receive focus.  In my cases, I usually toggle a className on the parent element to signal the element is active and thus the componentDidUpdate will trigger.

My perspective of inter-widget interaction has been formed by the days of Dojo's dijit UI framework where each widget usually had a reference to every child widget; with ReactJS the practice is (hopefully) avoiding refs and using state, which is logical but there's still that piece of me that longs for a simple reference, which is why the second strategy makes sense to me.

Recent Features

  • By
    Introducing MooTools Templated

    One major problem with creating UI components with the MooTools JavaScript framework is that there isn't a great way of allowing customization of template and ease of node creation. As of today, there are two ways of creating: new Element Madness The first way to create UI-driven...

  • By
    I&#8217;m an Impostor

    This is the hardest thing I've ever had to write, much less admit to myself.  I've written resignation letters from jobs I've loved, I've ended relationships, I've failed at a host of tasks, and let myself down in my life.  All of those feelings were very...

Incredible Demos

  • By
    MooTools History Plugin

    One of the reasons I love AJAX technology so much is because it allows us to avoid unnecessary page loads.  Why download the header, footer, and other static data multiple times if that specific data never changes?  It's a waste of time, processing, and bandwidth.  Unfortunately...

  • By
    AJAX For Evil:  Spyjax with jQuery

    Last year I wrote a popular post titled AJAX For Evil: Spyjax when I described a technique called "Spyjax": Spyjax, as I know it, is taking information from the user's computer for your own use — specifically their browsing habits. By using CSS and JavaScript, I...

Discussion

  1. Hi David.

    Great article — as always. It is just worth to update a syntax of reference to the now one (updated in 16.3) using

    React.createRef()

    .

    https://reactjs.org/docs/react-api.html#reactcreateref

    Thanks

  2. Alexis Wilke

    Note that the autofocus attribute has to be written autoFocus in React. Camel case all the way!

  3. Christopher

    I’d suggest componentDidMount() instead of componentDidUpdate() to avoid the issues with re-renders that you pointed out.

  4. Ariel

    actually, the syntax should be autoFocus={true}

  5. Akshra

    Yes correct Syntax is autoFocus={true} just simply add in your input element ,it also work in re-rendering .

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!