-
-
Notifications
You must be signed in to change notification settings - Fork 138
Description
Describe the bug
Hi, in a list of TextInputs, what I'm trying to achieve here is to create new item and focus it when return key is pressed from the keyboard.
This results in closing initially opened keyboard since blur is triggered when return key is pressed, and reopen the keyboard after new item is added and focused.
Newly added TextInput seems to avoid the keyboard just fine if the time between closing the keyboard and focusing new TextInput is very short, but once there's a delay in between those two actions, it doesn't avoid the keyboard.
The delay can be caused due to:
- Rendering added item takes time
- Adding new item and updating list is done by an API request
To simulate and reproduce this bug, I gave setTimeout of 100ms before adding new item. You can check it on addAndFocus function of below code.
I'm also posting a recorded video of this so I believe it'll be a lot easier to understand the issue by checking the video first.
Code snippet
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { FlatList, ListRenderItemInfo, StyleSheet } from 'react-native';
import { TextInput } from 'react-native-gesture-handler';
import { KeyboardAwareScrollView } from 'react-native-keyboard-controller';
type ListItem = {
id: string;
text: string;
};
const DATA: ListItem[] = [
{
id: '1',
text: 'Test1',
},
{
id: '2',
text: 'Test2',
},
{
id: '3',
text: 'Test3',
},
{
id: '4',
text: 'Test4',
},
{
id: '5',
text: 'Test5',
},
{
id: '6',
text: 'Test6',
},
{
id: '7',
text: 'Test7',
},
];
type Props = ListItem & {
isFocused: boolean;
onSubmit: () => void;
};
const Item = ({ id, text, isFocused, onSubmit }: Props) => {
const inputRef = useRef<TextInput | null>(null);
useEffect(() => {
if (isFocused) {
inputRef.current?.focus();
}
}, []);
return (
<TextInput
ref={inputRef}
style={styles.input}
value={text}
onSubmitEditing={onSubmit}
/>
);
};
export const TestKeyboardAwareList = () => {
const [data, setData] = useState<ListItem[]>(DATA);
const addedItemIdRef = useRef<string | undefined>();
const addAndFocus = useCallback(() => {
setTimeout(() => {
const newItemId = new Date().getTime().toString();
addedItemIdRef.current = newItemId;
setData((prev) => [...prev, { id: newItemId, text: '' }]);
}, 100);
}, []);
const renderItem = useCallback(
({ item }: ListRenderItemInfo<ListItem>) => {
const isFocused = addedItemIdRef.current === item.id;
return <Item {...item} isFocused={isFocused} onSubmit={addAndFocus} />;
},
[addAndFocus]
);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
keyboardDismissMode={'interactive'}
renderScrollComponent={(props) => {
return <KeyboardAwareScrollView {...props} />;
}}
/>
);
};
const styles = StyleSheet.create({
input: {
height: 80,
borderWidth: 1,
width: '100%',
},
});Repo for reproducing
Import above component in any screen
To Reproduce
Steps to reproduce the behavior:
- Tap on last item to focus it
- Tap return button to add new item at the bottom of the list
- New item is added and focused but it won't avoid the keyboard
Expected behavior
Added item should avoid the keyboard
Screenshots
Simulator.Screen.Recording.-.iPhone.15.-.2024-07-22.at.17.52.29.mp4
Smartphone (please complete the following information):
- Desktop OS: MacOS 14.5
- Device: iPhone 15 simulator
- OS: iOS 17.4
- RN version: 0.74.2
- RN architecture: old
- JS engine: Hermes
- Library version: 1.12.5
Additional context
n/a