개발새발 로그

React - useRef에 대하여 본문

React

React - useRef에 대하여

이즈흐 2023. 12. 11. 19:45

useRef

const ref = useRef(value);

함수형 컴포넌트에서 useRef를 부르면 ref 오브젝트를 반환해준다.

 

ref 오브젝트는 아래와 같다.

{current : value}

ref 오브젝트는 수정이 가능하기 떄문에 언제든 변경해줄 수 있다.

 

 

ret는 컴포넌트의 모든 생애주기에서 유지된다.

컴포넌트가 계속해서 렌더링이 되어도 언마운트되기까지 값을 그대로 유지할 수 있다.

 

useRef는 언제 사용이 될까?

두 가지 상황이 있다.

1. 저장공간을 위해

usestate의 state를 변경하면

자동으로 컴포넌트는 재 렌더링이 되고,

컴포넌트 내부 변수들은 초기화가 된다. -> let과 같은 변수는 초기화된다!

 

하지만 Ref를 이용하면

Ref가 변경되어도

렌더링이 되지않고,

컴포넌트 내부 변수들의 값이 유지된다.

-> 불필요한 렌더링을 막을 수 있다.

 

또한 state가 변경되어서 

계속 렌더링이 되어도 

Ref의 값은유지된다.

 

2. DOM 요소에 접근하기 위해

보통 input 요소에 focus를 줄 때 많이 사용된다.

바닐라JS의 Doccument.querySelector과 비슷하다.

 

 

useRef를 사용해야할 때 - 의존성 배열이 없는 useEffect에 setState를 사용하지 마라!

렌더링하는 횟수를 renderCount에 저장하려고한다.

하지만 아래처럼 작성하면 오류를 발생하게 된다.

// 렌더링을 하게되면 무한반복을 하게된다!
useEffect(()=>{
   setRenderCount(renderCount + 1);
});

setRenderCount가 실행하게되면 렌더링을 하게되고

또다시 useEffect가 실행된다.

이를 무한 반복하게 되는 것이다!

 

이 때 useRef를 사용하면 원하는 결과를 얻을 수 있다.

 

 

주의점!

렌더링 중에는 ref.current를 쓰거나 읽지 마세요.

React는 컴포넌트의 본문이 순수한 함수처럼 동작할 것으로 기대합니다:

- 입력(프롭, 상태, 컨텍스트)이 동일하다면 정확히 동일한 JSX를 반환해야 합니다.

- 다른 순서나 다른 인수를 사용하여 호출해도 다른 호출의 결과에 영향을 미치지 않아야 합니다

렌더링 중에 레퍼런스를 읽거나 쓰면 이러한 기대가 깨집니다.

function MyComponent() {
// ...
// 🚩 렌더링 중에 ref를 작성하지 마세요.
myRef.current = 123;
// ...
// 🚩 렌더링 중에 레퍼런스를 읽지 마세요.
return <h1>{myOtherRef.current}</h1>;
}

대신 이벤트 핸들러나 이펙트에서 참조를 읽거나 쓸 수 있습니다.

function MyComponent() {
	// ...
useEffect(() => {
    // ✅ 이펙트에서 레퍼런스를 읽거나 쓸 수 있습니다.
    myRef.current = 123;
    });
// ...
function handleClick() {
    // ✅ 이벤트 핸들러에서 참조를 읽거나 쓸 수 있습니다.
    doSomething(myOtherRef.current);
  }
    // ...
}

 

useRef를 사용해야 할 때 - DOM요소에 접근하기 위해

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        Focus the input
      </button>
    </>
  );
}

 

아래와 같이 지정하면 input의 대한 모든 정보를 얻을 수 있다.

ref={inputRef}

 

 

 

 

컴포넌트에 ref사용하는 법!

 

만약 ref를 사용하려는 요소가 하위 컴포넌트와 같이 다른  컴포넌트에 있더라도 ref로 추적할 수 있다.

 

상위 컴포넌트

import {useRef} from "react"
import MyInput from "./components/Input"

function App(){
    const inputRef = useRef()
    
    return(
    	<div>
            <MyInput ref={inputRef}/>
            <button onClick={()=> inputRef.current.focus()}>Focus</button>
        </div>
    );
}

 

하위 컴포넌트

import { forwardRef } from 'react';

const MyInput = forwardRef(({ value, onChange }, ref) => {
  return (
    <input
      value={value}
      onChange={onChange}
      ref={ref}
    />
  );
});

export default MyInput;

 

 

만약 위처럼 사용하지 않는다면 아래와 같이 오류가 발생한다.

const inputRef = useRef(null);

return <MyInput ref={inputRef} />;

이는 기본적으로 커스텀 컴포넌트는 내부의 DOM 노드에 대한 참조를 노출하지 않기 떄문이다.

728x90
반응형
LIST

'React' 카테고리의 다른 글

React - useMemo에 대하여  (1) 2023.12.11
React - useContext에 대하여  (1) 2023.12.11
React - useState에 대하여  (0) 2023.12.11
React - useEffect에 대하여  (0) 2023.12.11
React - 분기와 반복( 논리곱연산자,삼항연산자, map)  (1) 2023.12.05