I have an issue with focusing the next input in React Native. I use just one input called GeneralTextInput.tsx in the whole app.
In this example I have 2 inputs ==> 1.Group Name, 2.Group Description
So I give some props in the parent to this component:
<View style={classes.formContainer}> <Text style={classes.label}>{t("group.name-your-group")}</Text> <GeneralTextInput width={"100%"} returnKeyType={"next"} isDoneReference={false} deleteIcon startIcon={"account-multiple"} bordered={true} placeholder={t("form.placeholders.groupName")} value={props.newGroupName} onChange={(val: string) => { props.setNewGroupName(val); if (val.length > 25) { props.setNewGroupNameError(t("form.validations.max-25-char")); } if (val.length <= 25) { props.setNewGroupNameError(undefined); } }} /> <Text style={classes.label}>{t("group.describe-your-group")}</Text> <GeneralTextInput width={"100%"} returnKeyType={"done"} isDoneReference={true} isDismissed={true} startIcon={"text"} bordered={true} isMultiLine={true} numberOfLines={3} placeholder={t("form.placeholders.groupDescription")} value={props.newGroupDescription} onChange={(val: string) => { props.setNewGroupDescription(val); if (val.length > 30) { props.setNewGroupDescriptionError(t("form.validations.max-30-char")); } if (val.length < 30) { props.setNewGroupDescriptionError(undefined); } }} /> </View>
And this is my GeneralTextInput.tsx What should I give to the input as a ref and how should I focus on it?
import * as React from "react"; import { NativeSyntheticEvent, Platform, StyleProp, TextInputFocusEventData, TextStyle, View, ViewStyle, TextInput, ImageStyle, Pressable, } from "react-native"; import { makeStyles, IStyledComponent } from "../../assets/theme/installation"; import { IconButton, Text, useTheme } from "react-native-paper"; import Icon from "react-native-vector-icons/MaterialCommunityIcons"; import FontAwesome5Icon from "react-native-vector-icons/FontAwesome5"; import { theme } from "../../assets/theme/DefaultTheme"; import { TouchableWithoutFeedback } from "react-native-gesture-handler"; export interface IGeneralTextInputProps extends IStyledComponent<GeneralTextInputStyles> { readonly value: string | undefined; readonly placeholder?: string; readonly onChange: (newValue: string) => void; readonly onBlur?: (e: NativeSyntheticEvent<TextInputFocusEventData>) => void; readonly isPassword?: boolean; readonly autoCapitalize?: boolean; readonly error?: string; readonly startIcon?: string; readonly startIconFA5?: string; readonly endIcon?: string; readonly deleteIcon?: boolean; readonly disabled?: boolean; readonly disabledInputText?: boolean; readonly bordered?: boolean; readonly isMultiLine?: boolean; readonly width?: number | string; readonly numberOfLines?: number; readonly keyboardType?: string; readonly isGratitude?: boolean; readonly autoCorrect?: boolean; readonly selectedMeasureUnit?: string; readonly returnKeyType?: string; readonly isDoneReference?: boolean; readonly isDismissed?: boolean; } export const GeneralTextInput: React.FC<IGeneralTextInputProps> = ( props: IGeneralTextInputProps, ) => { const classes = useStyles(props); const { fonts, colors } = useTheme(); const [isPressed, setIsPressed] = React.useState(false); const [isPasswordVisible, setPasswordVisible] = React.useState(false); const groupNameRef = React.useRef<HTMLInputElement>(null); const groupDescRef = React.useRef<HTMLInputElement>(null); return ( <View style={classes.container}> <TouchableWithoutFeedback> <View style={classes.root}> <TextInput ref={() => (props.isDoneReference ? groupDescRef : groupNameRef)} onSubmitEditing={() => { groupDescRef.current?.focus(); }} blurOnSubmit={props.isDoneReference ? true : false} keyboardType={ props.keyboardType === "numpad" ? "numeric" : "default" } autoCorrect={props.autoCorrect} multiline={props.isMultiLine} numberOfLines={props.numberOfLines} maxLength={props.isGratitude ? 300 : 50} editable={!props.disabled} onBlur={props.onBlur} autoCapitalize={ props.autoCapitalize != undefined ? "words" : "none" } secureTextEntry={ props.isPassword == undefined ? false : !isPasswordVisible } style={ props.disabledInputText ? classes.disabledTextInput : classes.textInput } value={props.value} placeholder={props.placeholder} placeholderTextColor={fonts.text.small.color} onTouchEnd={() => setIsPressed(true)} onChangeText={(value) => props.onChange(value)} returnKeyType={ props.returnKeyType === "next" ? "next" : props.returnKeyType === "done" ? "done" : "default" } /> </View> </TouchableWithoutFeedback> </View> ); };
Advertisement
Answer
You wrap GeneralTextInput with forwardRef:
import { TextInput, TextInputProps } from "react-native"; export const GeneralTextInput: React.forwardRef<TextInput,IGeneralTextInputProps> = ( // type of props and ref will be inferred by ts props ref ) => { .... return ( .... <TextInput ref={ref} {...props} ... ... /> )}
Now in the parent component Define one useRef:
const secondInputRef = useRef<TextInput | null>(null);
you have 2 generalInput. on first input
<GeneralTextInput .... .... // add this. this will focus on secondInput onSubmitEditing={() => { secondInputRef.current?.focus(); }} />
second GeneralInput will be as it is