React.forwardRef()를 사용하여 컴포넌트의 타이머(Timer) 기능을 구현하는 방법에 대해 알려주세요.

React는 사소한 기능을 담당하는 리액트 컴포넌트를 만들 때 유용한 기능인 forwardRef()를 제공합니다. 이를 사용하면 해당 컴포넌트가 ref를 전달 받을 수 있게 됩니다.

이제 우리는 forwardRef()를 사용하여 타이머를 구현하는 컴포넌트를 만들어 보겠습니다.

컴포넌트 설계

타이머는 일정 시간 간격으로 실행되는 작업을 시각적으로 표시하는 기능을 제공합니다. 우리의 타이머 컴포넌트는 다음과 같은 기능을 갖추고 있을 것입니다:

  1. 처음 렌더링될 때 특정 초(second) 값을 전달 받습니다.
  2. 주어진 초 값부터 0까지 1초씩 카운트다운합니다.
  3. 카운트다운 과정을 화면에 실시간으로 표시합니다.
  4. 카운트다운이 완료되면 완료 콜백 함수를 호출합니다.

컴포넌트 구현

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

const Timer = forwardRef((props, ref) => {
  const [seconds, setSeconds] = useState(props.seconds);

  // ref에 접근하기 위한 변수 생성
  const timerRef = useRef(null);
  
  // 남은 초 값이 변경될 때마다 실행되는 효과
  useEffect(() => {
    if (seconds > 0) {
      // 1초마다 남은 초 값을 감소시킴
      timerRef.current = setInterval(() => {
        setSeconds(prevSeconds => prevSeconds - 1);
      }, 1000);
    } else {
      clearInterval(timerRef.current);
      props.onComplete();
    }

    // cleanup 함수
    return () => {
      clearInterval(timerRef.current);
    };
  }, [seconds]);

  // ref를 전달
  useEffect(() => {
    if (ref) {
      ref.current = {
        reset: () => setSeconds(props.seconds),
      };
    }
  }, [ref]);

  return <div>남은 시간: {seconds}</div>;
});

export default Timer;

컴포넌트 사용

import React, { useRef } from 'react';
import Timer from './Timer';

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

  const handleComplete = () => {
    console.log('타이머 완료!');
  };

  const handleReset = () => {
    timerRef.current.reset();
  };

  return (
    <div>
      <Timer seconds={10} ref={timerRef} onComplete={handleComplete} />
      <button onClick={handleReset}>타이머 리셋</button>
    </div>
  );
};

export default App;

위의 예제 코드에서는 forwardRef()를 사용하여 Timer 컴포넌트를 생성하였습니다. Timer 컴포넌트는 secondsonComplete props를 받고, ref를 전달받을 수 있도록 구성되어 있습니다.

타이머 컴포넌트 내부에서는 seconds 상태값이 변경될 때마다 useEffect() 훅을 통해 1초씩 감소시키는 작업을 진행하고, 카운트다운이 완료되면 onComplete 콜백 함수를 호출합니다.

타이머 컴포넌트를 사용하는 App 컴포넌트에서는 Timer 컴포넌트를 렌더링하고, reset 기능을 제공하기 위해 ref를 사용하여 타이머를 리셋하는 함수를 구현했습니다.

이제 위의 예제를 참고하여 forwardRef()를 사용하여 타이머 기능을 구현할 수 있습니다.

참고자료: React 공식 문서 - Refs and the DOM

해시태그

#React #컴포넌트