패스트캠퍼스 데브캠프 50~51일차 [React, useRef]

Su Min·2024년 7월 31일
post-thumbnail

🔗 useRef

useRef는 리액트 컴포넌트에서 변경 가능한 값을 유지하기 위해 사용하는 Hooks이다. useRef Hook을 사용하여 DOM요소에 접근하고 컴포넌트의 렌더링과 관련이 없는 값을 저장할 수 있다.

🔗 형식

const 변수명 = useRef( 초기값 )

useRef는 변경 가능한 current속성을 가진 하나의 객체 { current: 초기값 } 를 반환한다. useRef를 선언한 변수에는 current 키 값을 가진 property가 생성되고 값을 바꿀 때에도 current를 이용한다.

Current

import React, { useRef } from 'react'

const refContainer = useRef( value )

useRef안에 value를 넣어주면 ref객체 안에 있는 current property에 value가 할당된다. useRef로 생성된 객체는 컴포넌트의 생명주기 동안 유지되어 컴포넌트가 리렌더링되더라도 useRef로 저장된 값은 변경되지 않는다.

refContainer.current 값은 현재 참조하고 있는 element가 반환된다.

🔗 DOM 접근

import React, { useRef } from 'react';

const App = ({ addList }) => {
  const inputRef = useRef(null);

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={()=>addList(inputRef.current.value)}>추가</button>
    </div>
  );
}

DOM요소를 직접 참조하여 요소에 접근 할 수 있다. 위의 코드에서 inputRef 변수는 input 요소를 참조하여 해당 value를 부모 컴포넌트 함수의 인자로 넘겨주면 리렌더링이 발생하더라도 useRef로 관리되는 참조 값은 유지되어 부모 컴포넌트에 있는 함수는 자식 컴포넌트의 input값을 정상적으로 전달 받고 항상 최신의 input 값을 읽을 수 있다. 부모 컴포넌트로 전달되는 inputRef.current.value 가 변경되더라도 inputRef 객체 자체의 참조는 변하지 않기때문에 컴포넌트는 리렌더링되지 않는다.

Input Focus

어떠한 웹 페이지에서 로그인 화면을 들어가자마자 Id input창이 활성화 되는 것을 확인 할 수 있다. useRef와 useEffect를 사용하여 구현 가능하다.

import React, { useRef, useEffect } from 'react';

const App = () => {

  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return (
    <div id="signIn">
      <input ref={inputRef} type="text" placeholder="ID를 입력하세요."/>
    </div>
  );
}

위의 로직처럼 ID input이 useRef를 참조하도록 하면 컴포넌트가 마운트될 때 input 요소에 포커스를 설정할 수 있다.

렌더링 수 기록하기

const [value, setValue] = useState("")
const renderCountRef = useRef(0)

  useEffect(() => {
    renderCountRef.current++
  })
  
  return (
    <dlv className="App">
      <header className="App-header">
        <p>렌더링 횟수: {renderCountRef.current}</p>
        <input onChange={(e) => setValue(e.target.value)} value={value} />
      </header>
    </dlv>
  )

위의 코드에서 useEffect는 의존성 배열이 없어서 어떤 state든 변경되면 useEffect가 실행된다. 컴포넌트가 처음 렌더되는 순간을 포함하여 input의 값이 변경 될 때마다 renderCountRef는 값이 변하는 것을 확인 할 수 있다.

props로 전달

  • 부모컴포넌트
import React, { useRef } from 'react';

const App = () => {
  const inputRef = useRef(null);

  return (
    <div>
      <Child ref={inputRef} type="text" />
    </div>
  );
}
export default App
  • 자식컴포넌트
import React, { forwardRef } from "react"

const Child = forwardRef( props, ref ) => {
  return (
    <div>
		<input ref={ref} />
    </div>
  );
}
export default Child

자녀컴포넌트에서 props안에 ref를 가져오는 것이 아닌 props를 첫번째 인자로 가져오고 ref를 두번째 인자로 가져와야 한다. "ref" 이름이 아닌 다른 이름으로 내려줄때엔 forwordRef 없이도 자녀컴포넌트로 내려 줄 수 있다. 예를 들어 아래 로직처럼..

const Child = ( props ) => {
  const { inputRef } = props
  return (
    <div>
		<input ref={inputRef} />
    </div>
  );
}
export default Child

🔗 state와 useRef 차이점

state의 값이 변하면 컴포넌트가 리렌더링 되지만 useRef를 선언한 변수의 값이 변해도 컴포넌트는 리렌더링 되지 않는다.

  const [count, setCount] = useState(0)
  const countRef = useRef(0)

위의 로직에서 countRef의 값을 바꿔도 렌더링이 이러나지 않으며 useState를 사용한 count의 값을 바꿀 때 리렌더링이 되어 그제서야 countRef의 바뀐 값을 확인 할 수 있다. 이 과정에서 countRef의 값은 유지가 되는 것을 확인 할 수 있다.

🔗 let과 useRef 차이점

  const countRef = useRef(0)
  let countVariable = 0

변수는 ref와 다르게 컴포넌트가 렌더링 되면 다시 초기화되서 state값이 바뀌면 리렌더링 되기때문에 변수가 0으로 초기화된다.

이를 통해 Ref를 사용하여 변수를 용이하게 관리 할 수 있으며 쉽게 DOM 접근을 가능케한다.

profile
성장하는 과정에서 성취감을 통해 희열을 느낍니다⚡️

0개의 댓글