A React hook that wires up return-key focus chaining across form inputs with no explicit indices or refs.
npm install @rific/focus-chainCall register() once per input in render order. It returns ref and onSubmitEditing as spreadable props — no index tracking required.
import { useFocusChain } from '@rific/focus-chain'
function MyForm() {
const register = useFocusChain()
return (
<>
<TextInput {...register()} returnKeyType='next' placeholder='First name' />
<TextInput {...register()} returnKeyType='next' placeholder='Last name' />
<TextInput {...register()} returnKeyType='done' placeholder='Email' />
</>
)
}Pressing return on any input automatically focuses the next one. The last input receives no onSubmitEditing target, so nothing happens (pair it with returnKeyType='done' and your own submit handler).
The hook has no React Native dependency — its only requirement is elements exposing focus(), which DOM inputs do. On the web, wire onSubmitEditing to the Enter key yourself:
function WebForm() {
const register = useFocusChain()
const first = register()
const second = register()
return (
<>
<input ref={first.ref} onKeyDown={(e) => e.key === 'Enter' && first.onSubmitEditing()} />
<input ref={second.ref} onKeyDown={(e) => e.key === 'Enter' && second.onSubmitEditing()} />
</>
)
}Returns a register function. Call register() once per input during render, in the order inputs should be focused.
type Registration = {
ref: (el: { focus: () => void } | null) => void
onSubmitEditing: () => void
focus: () => void
}Both props are spread directly onto the input component.
- Stable render trees only — inputs registered conditionally (e.g. inside
{show && ...}) will shift indices when the condition changes. For conditional inputs, split them into separate chains or always render witheditable={false}. - Works with any focusable component, not just React Native
TextInput.