In a React Native checkout form, how do you move focus to the next TextInput when the user presses the keyboard's return key?
answer
- label the key, then handle it
- returnKeyType next, last one done
- onSubmitEditing calls ref.focus()
- submitBehavior submit keeps the keyboard
- number pads have no return key on iOS
basics
~10 sGive each field returnKeyType="next" (the last "done"), and in onSubmitEditing call the next field's ref.current?.focus(). Set submitBehavior="submit" on the chained fields so the keyboard stays up between them instead of blurring and reopening.
solid answer
~40 s`returnKeyType` only changes the key's label; the behaviour comes from `onSubmitEditing`, which fires when the return key is pressed, and a ref to the next field whose `focus()` you call there. For single-line inputs `submitBehavior` defaults to `'blurAndSubmit'`, which dismisses focus before your handler moves it, so chained fields use `submitBehavior="submit"` to keep the keyboard open; the last field keeps the default and submits the form. `blurOnSubmit` is the deprecated predecessor and is overridden by `submitBehavior`. `enterKeyHint` is the web-style alternative and takes precedence over `returnKeyType`. One trap: iOS number and phone pads have no return key. React Native adds a toolbar button above them only when the field sets a `returnKeyType` such as `'next'` or `'done'`; without one, `onSubmitEditing` never fires.
code
tsx · 43 linesimport {useRef, type ComponentRef} from 'react';
import {TextInput, View} from 'react-native';
type InputRef = ComponentRef<typeof TextInput>;
export function AddressForm({onPlaceOrder}: {onPlaceOrder: () => void}) {
const unitRef = useRef<InputRef>(null);
const postcodeRef = useRef<InputRef>(null);
const phoneRef = useRef<InputRef>(null);
return (
<View>
<TextInput
placeholder="Street address"
returnKeyType="next"
submitBehavior="submit"
onSubmitEditing={() => unitRef.current?.focus()}
/>
<TextInput
ref={unitRef}
placeholder="Apartment or unit"
returnKeyType="next"
submitBehavior="submit"
onSubmitEditing={() => postcodeRef.current?.focus()}
/>
<TextInput
ref={postcodeRef}
placeholder="Postcode"
returnKeyType="next"
submitBehavior="submit"
onSubmitEditing={() => phoneRef.current?.focus()}
/>
{/* On iOS the phone pad has no return key; returnKeyType adds a toolbar button. */}
<TextInput
ref={phoneRef}
placeholder="Phone for the courier"
keyboardType="phone-pad"
returnKeyType="done"
onSubmitEditing={onPlaceOrder}
/>
</View>
);
}go deeper
Recall that returnKeyType only labels the key and that onSubmitEditing plus a ref's focus() does the actual moving.
Explain submitBehavior's defaults for single-line and multiline fields, why submit avoids the keyboard bounce, and that blurOnSubmit is deprecated.
Handle the iOS number-pad case with a returnKeyType toolbar button, keep focused fields visible, and keep a visible submit path for users who never use the return key.
Standardise a form field component that encodes these conventions, so every team gets consistent keyboard flow without re-learning platform quirks.
## The pieces A good mobile form lets the user go from field to field with the keyboard's return key, without tapping each field. In React Native that takes four props and a ref per field: - **`returnKeyType`** sets the **label** of the return key: `'next'`, `'done'`, `'go'`, `'search'` and `'send'` work on both platforms; others are platform-specific. - **`onSubmitEditing`** is called when the return key is pressed; its `nativeEvent.text` is the field's text. - **A ref** to each `TextInput`, so the handler can call **`focus()`** on the next field. - **`submitBehavior`** decides what pressing return does to the current field. - **`enterKeyHint`** is the web-style name for the same label (`'next'`, `'done'`, `'enter'` and others). It takes precedence over `returnKeyType` if both are set; pick one. ## submitBehavior and why it matters `submitBehavior` accepts `'submit'`, `'blurAndSubmit'` and `'newline'`. | Field | Default when unset | Effect of return | |---|---|---| | single-line | `'blurAndSubmit'` | fires `onSubmitEditing`, then the field loses focus | | multiline | `'newline'` | inserts a newline; no submit | | any, set to `'submit'` | | fires `onSubmitEditing`, keeps focus | For a single-line field, `'newline'` is not meaningful and is treated as `'blurAndSubmit'`. With the single-line default, pressing return blurs the current field. Moving focus to the next field then reopens the keyboard, which can show as a visible dismiss-and-show bounce. Setting **`submitBehavior="submit"`** on every field except the last keeps the keyboard up while focus moves. The last field keeps the default so return dismisses the keyboard and submits. `blurOnSubmit` is the **deprecated** boolean this replaced. `submitBehavior` overrides it when both are present, so new code should not use `blurOnSubmit`. ## Wiring a four-field checkout form A grocery checkout asks for a street address, an apartment or unit, a postcode and a phone number for the courier. 1. Create a ref per field that needs to be focused programmatically. 2. Give the first three fields `returnKeyType="next"` and `submitBehavior="submit"`. 3. In each `onSubmitEditing`, call the next ref's `focus()`. 4. Give the last field `returnKeyType="done"` and let its `onSubmitEditing` validate and place the order. Refs are typed as the component's instance: `ComponentRef<typeof TextInput>` works everywhere, and under the Strict TypeScript API `TextInputInstance` is exported for the same purpose. ## The number-pad trap on iOS On iOS, the **number, decimal and phone pads have no return key**. A phone field with `keyboardType="phone-pad"` and no `returnKeyType` therefore gives the user no way to trigger `onSubmitEditing`, and the docs note that the method is not called for `phone-pad`. React Native works around this: when a field on one of those pads has a `returnKeyType` such as `'next'` or `'done'` set, its iOS text input adds a **toolbar above the keyboard with a button** labelled after that return key type, and pressing it submits just as a return key would. `inputAccessoryViewButtonLabel` replaces the button's label, which is not localized by default. The toolbar is an iOS-only workaround inside React Native's text input. ## Other details worth knowing - **Focus on mount** with `autoFocus` on the first field rather than calling `focus()` in an effect. - **`blur()`** and **`isFocused()`** are the companion methods on the same ref. - **Keep the focused field visible.** Moving focus down a long form means the next field may be under the keyboard; avoiding that is keyboard-avoidance work, separate from focus chaining. - **Do not rely on the return key alone.** A visible **Continue** button is still needed for users who dismiss the keyboard or use assistive technology. ## Checklist for a keyboard-friendly form - every field except the last: `returnKeyType="next"`, `submitBehavior="submit"`, `onSubmitEditing` focusing the next ref; - the last field: `returnKeyType="done"` (or `'go'`/`'send'`), default `submitBehavior`, `onSubmitEditing` submitting; - number and phone fields on iOS: a `returnKeyType` set so the toolbar button appears, with `inputAccessoryViewButtonLabel` if the label must be localized; - no `blurOnSubmit` in new code; - a visible submit button regardless of keyboard flow.
- In React Native, why does the keyboard briefly close and reopen when onSubmitEditing focuses the next single-line TextInput?A single-line field's `submitBehavior` defaults to `'blurAndSubmit'`: pressing return fires `onSubmitEditing` and then blurs the field, so the keyboard can start to dismiss before the next field takes focus and brings it back. Setting `submitBehavior="submit"` on the chained fields submits without blurring, so focus moves while the keyboard stays open.
- In React Native, what happens if a TextInput sets both enterKeyHint and returnKeyType?`enterKeyHint` wins: `TextInput` maps it to a return key type and ignores `returnKeyType`. The two exist because `enterKeyHint` mirrors the web attribute name while `returnKeyType` is React Native's original prop, with more platform-specific values. Use one consistently in a codebase.
- In React Native on iOS, how does a phone-pad TextInput let the user submit, given the pad has no return key?If the field sets a `returnKeyType` such as `'next'` or `'done'`, React Native's iOS text input adds a toolbar above the number or phone pad with a button named after it, and pressing it fires `onSubmitEditing` like a return key. Without a `returnKeyType` there is no toolbar and no way to submit from the keyboard. `inputAccessoryViewButtonLabel` provides a localized label.
saying these in an interview costs you the question
- returnKeyType="next" moves focus to the next field automatically.
- blurOnSubmit is the current way to keep the keyboard open between fields.
- onSubmitEditing fires for every keyboard type on iOS without extra setup.
- submitBehavior 'newline' makes a single-line field insert a line break.
- Focus chaining needs a third-party library in React Native.