physicsboy
physicsboy

Reputation: 6348

Can't enable and focus input at the same time

I have an input that will be disabled by default, but at the click of a button I would like to simultaneously enable and focus the input.

I have attempted this in the same function, however it doesn't seem to work in my IDE/local react environment, and requires clicking the button twice to do this once will enable the input and the second will focus it... It is very strange to me

enter image description here

App.jsx

export const MyConstant = () => {
    const [isDisabled, setIsDisabled] = useState(true);
    const myInput = useRef();

    const enableAndFocus = () => {
        setIsDisabled(false);
        myInput.current.focus();
    }

    return (
        <button onClick={() => enableAndFocus()}>ClickMe</button>

        <input ref={myInput} disabled={isDisabled} />
    )
}

Here is a stackblitz of the issue

I can't understand why it won't do them together... Is it because the state change is slower than the focus?

Upvotes: 0

Views: 1160

Answers (3)

Prayag Choraria
Prayag Choraria

Reputation: 819

You can have an useEffect hook which is listening for the isDisabled change and then you can focus on the input inside the hook if the isDisabled is false.

export const MyConstant = () => {
    const [isDisabled, setIsDisabled] = useState(true);
    const myInput = useRef();
    
    useEffect(() => {
        !isDisabled && myInput.current.focus();
    }, [isDisabled])

    const enableAndFocus = () => {
        setIsDisabled(false);
    }

    return (
        <button onClick={() => enableAndFocus()}>ClickMe</button>

        <input ref={myInput} disabled={isDisabled} />
    )
}

Upvotes: 1

Priyank Kachhela
Priyank Kachhela

Reputation: 2635

setIsDisabled is async function so when myInput.current.focus() executes your input is still disabled.

To fix this try to use useEffect hook like below:-

  useEffect(() => {
    if (!isDisabled) {
      myInput.current.focus();
    }
  }, [isDisabled]);

Upvotes: 1

Jeremy Thille
Jeremy Thille

Reputation: 26390

I don't work with React, but I guess you can do a little trick like this, to allow React to "digest" the enabled state before focusing the input :

const enableAndFocus = async () => {
        setIsDisabled(false);
        await Promise.resolve();
        myInput.current.focus();
}

Upvotes: 1

Related Questions