Using react-final-form
i am unable to forwardRef
to my TextInput
for React Native. The ref
is required for handling the Next
button in keyboards and other forced-focus events in forms.
My setup is as follows - please note that some code has been removed for simplicity so this won't cut and paste.
// FormInputGroup/index.js
import React from 'react'
import PropTypes from 'prop-types'
import { Field } from 'react-final-form'
const FormInputGroup = ({ Component, validate, ...rest }) => (
<Field component={Component} validate={validate} {...rest} />
)
FormInputGroup.propTypes = {
name: PropTypes.string.isRequired,
Component: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
validate: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
}
export default FormInputGroup
// Form/index.js
import { Form } from 'react-final-form'
import { FormInputGroup, FormInputText, ButtonPrimary } from '/somewhere/'
...
const passwordInputRef = useRef()
<Form
onSubmit={({ email, password }) => {
// submit..
}}
>
{({ handleSubmit }) => (
<>
<FormInputGroup
name="email"
Component={FormInputText}
returnKeyType="next"
onSubmitEditing={() => passwordInputRef.current.focus()}
blurOnSubmit={false}
/>
<FormInputGroup
name="password"
Component={FormInputText}
returnKeyType="go"
onSubmitEditing={handleSubmit}
ref={passwordInputRef} // <-- This does not work which i think is to be expected...
/>
<ButtonPrimary loading={loading} onPress={handleSubmit}>
Submit
</ButtonPrimary>
</>
)}
</Form>
...
// FormInputText/index.js
const FormInputText = forwardRef( // <-- added forwardRef to wrap the component
(
{
input,
meta: { touched, error },
label,
...
...rest
},
ref,
) => {
return (
<View style={styles.wrapper}>
{label ? (
<Text bold style={styles.label}>
{label}
</Text>
) : null}
<View style={styles.inputWrapper}>
<TextInput
onChangeText={input.onChange}
value={input.value}
...
ref={ref}
{...rest}
/>
</View>
</View>
)
},
)
I think the code falls down with the <FormInputGroup />
component. A clue to this is if i change the rendering on the form to be as follows;
...
<FormInputGroup
name="password"
Component={props => <FormInputText {...props} ref={passwordInputRef} />} // <-- changed
returnKeyType="go"
onSubmitEditing={handleSubmit}
/>
...
This does seem to forward the ref, but "breaks" final-form
with each keystroke dismissing the keyboard, presumably due to a re-render.
You didn't forward the ref from
FormInputGroup
.You need to capture the ref at the level it is passed down and further forward it to the children. This is how it should be: