ReactJS and autofocus
Asked Answered
C

4

9

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

Clement answered 5/7, 2019 at 3:27 Comment(1)
Does this answer your question? How to set focus on an input field after rendering?Internationalist
E
7

Refs is what you want,

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

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

<input type="text"  ref={this.myRef} />
Europeanize answered 5/7, 2019 at 3:31 Comment(4)
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.Clement
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.Europeanize
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.Slothful
Yes, you can do so. Refer the Callback Refs section from link I have provided in answer.Europeanize
M
13

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.

Mitzvah answered 28/1, 2020 at 4:49 Comment(2)
Awesome solution.Nertie
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.Demolition
E
7

Refs is what you want,

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

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

<input type="text"  ref={this.myRef} />
Europeanize answered 5/7, 2019 at 3:31 Comment(4)
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.Clement
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.Europeanize
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.Slothful
Yes, you can do so. Refer the Callback Refs section from link I have provided in answer.Europeanize
B
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.

Bangup answered 10/11, 2020 at 22:1 Comment(2)
What if the inputId changes? You probably want to use a dependency array with useEffect instead of relying on useState.Tridentum
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!Bangup
Z
0

For me, adding an autoFocus prop did the trick:

<input autoFocus {...} />
Zombie answered 17/3, 2024 at 7:8 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.