8

I have a react-bootstrap modal with an <input>. I want to set the autofocus attribute on the <input>

The following works fine, but shows a warning in the console

<input type="text" autofocus='true' />
Warning: Invalid DOM property `autofocus`. Did you mean `autoFocus`?

The following options do not work, in the sense that they do not focus the input when opening the modal:

<input type="text" autoFocus='true' />
<input type="text" autoFocus={true} />
<input type="text" autoFocus />

What is the recommended way of setting autofocus. Or how should I mute the warnings for the example that works well?

Note: This is react 16.8.6

Andrei Cioara
  • 3,404
  • 5
  • 34
  • 62
  • Does this answer your question? [How to set focus on an input field after rendering?](https://stackoverflow.com/questions/28889826/how-to-set-focus-on-an-input-field-after-rendering) – Aryan Beezadhur Jan 10 '21 at 21:13

3 Answers3

11

If you're using React Hooks, add useCallback() to your component and add a ref={callback} to the form control:

import React, { useCallback } from 'react'

function InputComponent() {
    const autoFocus = useCallback(el => el ? el.focus() : null, [])

    return <input type="text" ref={autoFocus} />
}

export default InputComponent

You can replace the <input> with a React Bootstrap FormControl too.

Brent Washburne
  • 12,904
  • 4
  • 60
  • 82
  • Awesome solution. – tomasconnor Aug 18 '20 at 10:43
  • 2
    Why are using `useCallback` instead of `useRef` here? Isn't `useCallback` rather for the purpose of keeping the identity of callbacks to avoid unnecessary re-renders? My understanding was that the use case here requires rather `useRef` + `useEffect`. – bluenote10 Dec 08 '20 at 15:49
5

Refs is what you want,

constructor(props) {
    super(props);
    this.myRef = React.createRef();
}

componentDidMount(){
  this.myRef.current.focus();
}

<input type="text"  ref={this.myRef} />
ravibagul91
  • 20,072
  • 5
  • 36
  • 59
  • I was hoping there is some more HTML way. But the variant I claimed "worked" doesn't actually work when you open the modal for the second time. – Andrei Cioara Jul 05 '19 at 03:42
  • `componentDidMount` work in mounting phase only, when you reopen your modal then your component don't go through `componentDidMount` function and you will not get focus here. For that you need some other lifecycle method like `componentDidUpdate`. – ravibagul91 Jul 05 '19 at 03:46
  • 1
    You can still use `autoFocus` if you have `ref={this.setMyRef}`, the `setMyRef` handler being a function that sets the implicitly passed input ref as a parameter bound to the input html element. It makes sense to create a wrapper component for input element for these cases. – Yeysides Jul 05 '19 at 03:48
  • 1
    Yes, you can do so. Refer the `Callback Refs` section from link I have provided in answer. – ravibagul91 Jul 05 '19 at 03:52
0

If you are using react hooks, you could write your own simple auto focus hook:

import { useEffect, useState } from "react";

export const useAutoFocus = (inputId: string) => {
    const [initialized, setInitialized] = useState(false);
    useEffect(() => {
        if(!initialized) {
            document.getElementById("email").focus();
            setInitialized(true);
        }
    });
};

and the simply use e.g.

useAutoFocus("email")

in your form.

Michael Baarz
  • 406
  • 5
  • 17
  • 1
    What if the inputId changes? You probably want to use a dependency array with useEffect instead of relying on useState. – Jack Nov 12 '20 at 10:58
  • This is only for initial focus because newest react throws an error with html attribute autofocus even if it works physically. Feel free to adjust to your needs! – Michael Baarz Nov 13 '20 at 11:31