StudioWorks
StudioWorks

Reputation: 493

How can I use forwardRef in functional component in react native?

I made the following screen where each label + input combo is inside a child component. When I click save (salvar) I want to inspect each component's ref to see if it has a "isInvalid" variable set to true and then paint the border red and show an error message. That means the field is required, etc.

enter image description here

I've tried creating a ref in the parent component like this:

export default function DiaryExam({ navigation }) {

let examNameRef =  useRef();

return (
    <Page type="static" title={'Avaliação'} subtitle={'Editar'}>
            <FormInput ref={examNameRef} inputType="text" title={"Nome da avaliação"} value={name} setValue={setName} required />
            //I'll add the other refs below later
            <FormInput inputType="text" title={"Código"} value={code} setValue={setCode} maxLength={8} required/>
            <FormInput inputType="number" title={"Nota máxima"} value={maxGrade} setValue={setMaxGrade} />
            <FormInput inputType="number" title={"Peso"} value={weight} setValue={setWeight} required />
            <FormInput inputType="date" title={"Data de Início"} value={startDate} setValue={setStartDate} />
            <FormInput inputType="date" title={"Data de Fim"} value={endDate} setValue={setEndDate} />
            <FormInput inputType="switch" title={"Ignorar na Fórmula"} value={ignoreFormula} setValue={setIgnoreFormula} />
            <Button style={[styles.button, {}]} textStyle={styles.buttonText} title={'Salvar'} onPress={() => saveExam()} requestFeedback />
    </Page>
);

In the child component I have something like this ( among other things) :

export default function FormInput ({ inputType, title, value, setValue, required, maxLength, ref }) {

return (
    <View>
        {(inputType === 'text' || inputType === 'number') && (
            <View>
                <Text ref={ref} style={[styles.fieldValue, { borderColor: requiredValidationError ? 'red' : 'grey' }]}>{value}</Text>
                <Text style={[{ alignSelf: 'flex-end', backgroundColor: 'white', color: requiredValidationError ? 'red' : 'grey' }]}>{requiredValidationError? 'Campo obrigatório' : ''}</Text>
            </View>
        )}
        </View>
)

I need to see if the 'value' variable is length === 0 if the 'required' prop is true and then set setRequiredValidationError(true) so it'll change the layout accordingly.

But all I get is the following error in the console:

[Tue Mar 09 2021 17:21:48.858]  ERROR    Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

I have googled react native forwardRef, but all the examples and documentations are for traditional React or they use class components and nothing I've tried works. How would I do that?

Upvotes: 0

Views: 11636

Answers (1)

P.E. Jo&#235;ssel
P.E. Jo&#235;ssel

Reputation: 1443

As per the warning, you need to use React.forwardRef. You can do it like this:

const FormInput = React.forwardRef(({ 
    inputType, 
    title, 
    value,
    setValue, 
    required, 
    maxLength
}, ref) => {
    return (
        {(inputType === 'text' || inputType === 'number') && (
            <View>
                <Text ref={ref} style={[styles.fieldValue, { borderColor: requiredValidationError ? 'red' : 'grey' }]}>{value}</Text>
                <Text style={[{ alignSelf: 'flex-end', backgroundColor: 'white', color: requiredValidationError ? 'red' : 'grey' }]}>{requiredValidationError? 'Campo obrigatório' : ''}</Text>
            </View>
        )}
    )
}

More info in the React doc, which uses functional component.

Upvotes: 3

Related Questions