Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

autoFocus on input when opening modal does not work - React Bootstrap

I have a modal that has 3 components. Each component represents a stage, so for example the first component is inputing the user's first name when the user click next, and it will go to the next component, which is inputing address and then user clicks next and it will take the user to the last stage, inputing a nickname. On every input element from the components, it will have an autoFocus. So far in the last two components, the inputs have an autoFocus except for the first component.

Not sure why the first doesn't have it, when I initialise the modal I see the input doesn't have the autoFocus, then I hit next then the second component input has it and I go back to the first component - hit the back button - then I see the input from the first component has an autoFocus. Very strange, I've been trying so many way to resolve this, from setting autoFocus={false} to the modal, creating a ref for the first input but still not working.

It looks like it's an issue with the modal, where it's initialized the focus is somewhere but not on the input. Has anyone encountered this issue?

Example (pseudo) code

//Component Hosting the modal

render(){

    if(this.state.modal_stage === 1){
        <FirstName />
    }else if(this.state.modal_stage === 2){
        <LasgtName />

    }else if(this.state.modal_stage === 3){
        <NickName />
    }
    return(

        <Modal 
            dialogClassName="locationModal customModal"
            show={this.state.modalShow} onHide={this.hideModal}
            autoFocus="false">
            <Modal.Header>
                <div className="closeModal" onClick={this.hideModal}></div>
            </Modal.Header>

            <Modal.Body>

                { current_stage}

            </Modal.Body>

            <Modal.Footer>
                {backButton}
                {nextButton}
            </Modal.Footer>

        </Modal>


    );
}


//<FirstName /> component

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

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

....

render(){


    return(
        <div>
            <input type="text" placeholder="firstName" ref={this.inputRef}/>
        </div>
    );
}

Your help will be appreciated!!

Note:

I tried to set this autoFocus="false" to autoFocus={false} in the modal but the issue still remains.

like image 575
medev21 Avatar asked Nov 13 '19 03:11

medev21


People also ask

How do you set focus on modal react?

Just add autoFocus = {false} on modal and autoFocus = {true} on input.

How can you prevent modal from closing when clicking outside react?

You can prevent closing of modal dialog by setting the beforeClose event argument cancel value to true.

How do you trigger a modal in react?

Add The State and MethodsAdd a button inside the render block to trigger the modal. When the button is clicked, the isOpen state will be set to true. Now, to display the modal, all you need to do is pass the isOpen state value to the show prop of the <Modal /> component.

What is autoFocus in react?

Autofocus can make your app more convenient for users. For example, instead of clicking into a field before typing, they can immediately start typing as soon as a form loads.


3 Answers

Here is a similar solution as the one from @dev_junwen using a functional component and hooks. Also no need for a timeout.

import React, { useEffect, useRef } from 'react';

const FirstInput = ({ item, save }) => {
    const innerRef = useRef();
    useEffect(() => innerRef.current && innerRef.current.focus());

    return <input ref={innerRef} />;
};
like image 132
mprivat Avatar answered Oct 21 '22 12:10

mprivat


Found out a solution that will fix your problem. You can add a little timeout for your component to focus on your input. This should fix your issue.

class FirstInput extends React.Component {
  constructor(props) {
    super(props);
    this.innerRef = React.createRef();
  }

  componentDidMount() {
    // Add a timeout here
    setTimeout(() => {
      this.innerRef.current.focus();
    }, 1)
  }

  render() {
    return <input ref={this.innerRef} />;
  }
}

This is a working example: https://codesandbox.io/s/react-bootstrap-autofocus-efkve?fontsize=14

like image 30
junwen-k Avatar answered Oct 21 '22 11:10

junwen-k


Apparently there is a bug with react-bootstrap that doesn't allow autoFocus on a Modal component. The workaround while this bug is fixed is disabling animations on the Modal component.

    <Modal animation={false}>
      <Form.Control autoFocus />
    </Modal>
like image 31
Hugo Ramirez Avatar answered Oct 21 '22 11:10

Hugo Ramirez