Search code examples
reactjsreact-nativereact-native-elements

React Native: How to open the keyboard programmatically after closing a modal?


Let's consider the following situation:

There is a page with an Input and a Button to open a modal.

In the modal, there is the other Button to close this modal, to focus the Input and to show the Keyboard.

The problem:

Right after pressing the other Button to close the modal, to focus the Input and to show the Keyboard the following happens:

  1. The modal is closed.
  2. The Input has focus.
  3. But the Keyboard is NOT shown.

This is my code:

import React, { useState, useEffect, useRef } from 'react';
import { View } from 'react-native';

import { Button, Input, Overlay } from 'react-native-elements';

const App = () => {
  const [isInputFocused, setInputFocused] = useState(false);
  const [isModalVisible, setModalVisible] = useState(false);

  const inputRef = useRef(null);

  useEffect(() => {
    isInputFocused ? inputRef.current.focus() : inputRef.current.blur();
  }, [isInputFocused]);

  const handleInputFocus = () => setInputFocused(true);
  const handleInputBlur = () => setInputFocused(false);

  const handleOpenModalButtonPress = () => setModalVisible(true);

  const handleFocusInputButtonPress = () => {
    setModalVisible(false);

    setInputFocused(true);
  };

  const handleModalBackdropPress = () => setModalVisible(false);

  return (
    <View style={{ justifyContent: 'space-around', flex: 1, padding: 25 }}>
      <Input
        ref={inputRef}
        onFocus={handleInputFocus}
        onBlur={handleInputBlur}
      />

      <Button
        title="Open Modal"
        onPress={handleOpenModalButtonPress}>
      </Button>

      <Overlay visible={isModalVisible} onBackdropPress={handleModalBackdropPress}>
        <Button title="Focus Input and Open Keyboard" onPress={handleFocusInputButtonPress} />
      </Overlay>
    </View>
  );
};

export default App;

You can see it live here.

The question:

Is it possible to open the keyboard programmatically? It would probably solve my problem.

If not, could somebody explain what I am missing with my current approach or suggest a different solution?

Thanks in advance.

P.S.


Solution

  • It appears there are two issues:

    1. Keyboard will not appear if input is given focus while the modal is being dismissed - focus needs to be delayed until the dismiss animation completes, eg. with a timeout:

    setTimeout(() => setInputFocused(true), 500);

    1. As you pointed out, this fixed the issue only on first try - after reopening the modal, the keyboard does not show up anymore. This is because showing the modal dismisses the keyboard but, at least on Android, does not drop focus from the input. Giving it the focus again will have no effect and the keyboard will not appear. In this limited scope, a fix would be to drop focus manually when the modal is shown:
    const handleOpenModalButtonPress = () => {
        setModalVisible(true);
    
        setInputFocused(false);
    };
    

    Perhaps there is a more general solution.