forwardRef

박경수·2025년 1월 14일
0

두개이상의 ref

react native 공부를 하며 회원가입과 로그인의 form 작업을 진행중이다.

// InputField 컴포넌트

const innerRef = useRef<TextInput | null>(null);
    
const handlePressInput = () => {
    innerRef.current?.focus()
}
    
<Pressable onPress={handlePressInput}>
	<TextInput
	    ref={innerRef}
    />
	{error && <Text style={styles.error}>{error}</Text>} // error 영역
</Pressable>

상황

포커스 이동

const passwordRef = useRef<TextInput | null>(null);

<InputField
	returnKeyType="next"
    blurOnSubmit={false}
	onSubmitEditing={()=> passwordRef.current?.focus()}
	placeholder="이메일"
  />

<InputField ref={passwordRef} placeholder="비밀번호" />  // 해당 컴포넌트는 이미 내부에 ref가 존재

이메일을 입력하고 비밀번호로 이동할때 next를 누르면 비밀번호로 이동하도록 했다.
이미 <Pressble />을 이용해 ref를 사용하고 있어, 두개의 ref를 사용해야한다.

forwardRef

순서는 아래와 같다.

  1. <inputField/>forwardRef로 감싸준다.
  2. 외부에서 받은 ref(파라미터), 내부의 ref(로컬)를 병합한다.
import React, { ForwardedRef, forwardRef, useRef } from "react";
import { Dimensions, StyleSheet, TextInput, View, TextInputProps, Text, Pressable } from "react-native";

const InputField = forwardRef(({ ...props }, ref: ForwardedRef<TextInput>) => { // 외부 ref
    const innerRef = useRef<TextInput | null>(null); // 내부 ref
    
    const handlePressInput = () => {
        innerRef.current?.focus()
    }
    return (
        <Pressable onPress={handlePressInput}>
            <TextInput
                ref={ref ? mergeRefs(innerRef, ref) : innerRef} // ref 병합 진행
            />
                
        </Pressable>
    )
});
// mergeRefs

import { ForwardedRef } from "react"; // refs의 타입을 받는다.

function mergeRefs<T>(...refs: ForwardedRef<T>[]) { //ForwardedRef은 다수를 받도록 리스트로 받음.
    return (node: T) => {// return node는 dom요소나 react 컴포넌트 이다. 
        refs.forEach(ref => {// 순회하며, 함수인지 객체인지 확인한다.
            if (typeof ref === 'function') {
                ref(node)
            } else if (ref) {
                ref.current = node;
            }
        })
    }
}

export {mergeRefs}

마무리

이로써, 포커스 이동과 TextInput영역 클릭 ref 둘다 사용할 수 있다.

profile
<>{...}</>

0개의 댓글