Developer/React

React , 예제로 살펴보는 useRef /Ref 요소 선택 객체 사용 3

단님 2024. 6. 16. 22:30
728x90
useRef 의 
객체로의 사용을 살펴보자.

1. import ! useRef !

import { useRef } from 'react';

 

2.컴포넌트 내의 useRef객체 생성.

    const inputEle = useRef({
        name: null,     
        phoneNum: null,   
    });

객체 내부를 미리 정의 해야할 필요는 없지만.

우리의 명시성을 위해 null로 지정해주자.

 

name에는 이름입력에 해당하는 input을

phoneNum에는 전화번호 입력에 해당하는 input을 지칭할것이다.

그이후 각각의 클릭이벤트를 통해 각 해당하는 input 의 속성을 바꿔보려한다.

 

-컴포넌트 내부 return-

    return (
        <>
            <div>
                <label>
                    이름
                    <input type="text" ref={ele => inputEle.current.name = ele} />
                </label>
                <button onClick={registeredName}>등록</button>
            </div>

            <div>
                <label>
                    전화번호
                    <input type="text" ref={ele => inputEle.current.phoneNum = ele} />
                </label>
                <button onClick={registeredPhoneNum}>등록</button>
            </div>
        </>

ref 는 콜백 인자를 자기 자신을 지칭하게 됨 . (e.target 과 같은 역할.)

ele가 결국 input 요소 지칭하게 됨.

 

-버튼 온클릭 이벤트 -

    function registeredName() {
        inputEle.current.name.disabled = true;
        inputEle.current.phoneNum.focus();
        console.log(inputEle.current);
        console.log('클릭후');

    }

    function registeredPhoneNum() {
        inputEle.current.phoneNum.disabled = true;
        console.log(inputEle.current);
        console.log('클릭후');
    }
    
    console.log(inputEle.current);
    console.log('랜더링');
 	setTimeout(() => {
    console.log(inputEle.current);
    console.log('랜더링 후 1 초뒤 출력');
    }, 1000);

 

첫 마운트 상황에서는 null을 반환하지만,

1초뒤에(돔요소가 충분히 다 업데이트 된 후)는 input 이 해당하는 곳에 값이 들어가 있다.

 

클릭한 후에는 자기 요소가 들어가 있는 상태에서 온클릭 이벤트가 발생된다.

useRef는 랜더링에 방해받지 않음으로 인해 랜더링이 추가로 발생하지 않아

오류없이 출력이 가능함을 확인 가능.

 


안그래도 useRef는 객체인데 또다시 객체형태고 하니
코드가 길어요...
구조분해 할당을 사용하고 싶어요.
inputEle.current.name.disabled = true;
inputEle.current.phoneNum.focus();

 

이전과 같은 상황에서 값을 찾아가기 위해 이렇게 조금 길어지는 모습을 보였다.

 

그럴때 우리는 무엇을 사용했던가 ?

바로 구조분해 할당 !

속성과 변수가 같으면 변수에 할당되는 그 요망한 능력 !

 

const { name, phoneNum } = inputEle.current;

 

이렇게 쓰고 싶은데요 !!

 

 아... 네, 좋은데 처음엔 뭐라고 했죠 ..? null !!

 

첫 마운팅 시점에 돔 요소를 그릴때 까지의 딜레이가 발생하니,

컴포넌트 내에 바로 사용하면 초기의 null 값만 할당되게 된다.

 

ref 값을 가져오자!

    function getElement(ele) {
        inputEle.current[ele.name] = ele;
    }

ele.name은 각각의 input 요소의 name 속성 값이다.

예를 들어, ele.name이 "name"이라면 inputEle.current["name"] = ele가 된다.

 

잠깐 ,!!!! 혹시 객체 접근방식에서 대괄호가 어색하다면.

 

객체 접근 방식엔 두가지가 있다.

  • 점 표기법 (Dot notation)
  • 대괄호 표기법 (Bracket notation)

우리에게 아마 친숙한 것은 점 표기 법일것이다.

 

대괄호 표기법은

속성 이름이 동적으로 결정될 때 사용된다.

즉, 속성 이름이 변수로 주어질 때 유용하다.

const obj = {};
const propName = "name";
obj[propName] = "John";
console.log(obj[propName]); // John

 

 

여기서 보는 대괄호 표기된 함수를 읽어보면,

    function getElement(ele) {
        inputEle.current[ele.name] = ele;
    }

inputEle.current[ele.name] = ele;에서 ele.name은 동적으로 결정되는 값.

즉, ele.name이 무엇이든 간에 그 값을 속성 이름으로 사용하여 inputEle.current 객체에 저장하겠다는 의미가 된다.

 

클릭 함수를 만들자 !

function registeredName() {

        const { name, phoneNum } = inputEle.current;

        name.disabled = true;
        phoneNum.focus();
    }

    function registeredPhoneNum() {

        const { phoneNum } = inputEle.current;

        phoneNum.disabled = true;
    }

 

클릭과 동시에 구조분해 할당을 받으면 null 이 반환되지 않겠다.

클릭이벤트 내에서 구조분해 할당을 사용한다면 null 의 문제가 해결된다.