본문 바로가기
프론트엔드/React

리액트 useRef(2) 변수관리

by 랼랼 2022. 5. 10.

useRef는 rerendering되어도 변하지 않는 변수를 관리한다.

useRef는 DOM을 선택하는 기능뿐만 아니라, 리랜더링되어도 초기화되지 않는 변수를 관리할 수 있습니다.

 

이러한 특징을 이용해 스톱워치를 만들어 보겠습니다.

 

1) 선언

function StopWatch(){

    //ref 객체
    const timeRef = useRef(null);
    //start 작동 여부 판별할 state
    const [isStartOperation,setIsStartOperation]=useState(false);
    //경과 시간 state
    const [count,setCount]=useState(0);

시간 증가와 관련있는 timeRef를 useRef를 이용해 선언합니다.

start 버튼 클릭 여부를 판별할 isStartOperation을 false로 초기화하고,

경과된 시간을 표시하기 위한 count를 0으로 초기화하여 state에 넣어줍니다.

 

2) 작동 handler - start

//start 버튼 작동
const startHandler=()=>{
    //start 작동 안했다면
    if(!isStartOperation){
        //start 작동 체크
        setIsStartOperation(true);
        //ref 객체에 interval 설정 
        timeRef.current = setInterval(()=>{
            //interval에서 count 증가
            setCount((x)=>x+1);
        }
        //100 ms 마다
        ,100
        );
    }
}

start 버튼 작동 여부를 판별하고, 작동하지 않았다면 작동 여부를 true로 변환해줍니다.

(이 작업을 하지 않는다면, start버튼을 연속으로 누를때마다 interval이 실행되어 놀라운 가속 시간을 보여줍니다(!))

timeRef.current에 100 ms 마다 count를 1씩 증가시켜줍니다.

setInterval 내에서 count를 증가시키려면 setCount((x)=>x+1) 과 같이 적어야

100 ms마다 값이 갱신됩니다.

 

3) 작동 handler - stop

//정지
const stopHandler=()=>{
    //start 작동 false 체크
    setIsStartOperation(false);
    //ref 객체에 interval 정지
    clearInterval(timeRef.current);
}

isStartOperation을 false로 바꾸고 clearInterval을 통해 타이머를 정지시킵니다.

 

4) 작동 handler - reset

//리셋
const resetHandler=()=>{
    stopHandler();
    setCount(0);
}

stop을 실행하고, count를 0으로 초기화시킵니다.

 

5) jsx

    return(
        <div className="stopwatch">
            <div className="stopwatch_title">
                스톱워치
            </div>
            <div className="timer">
            {parseInt(count/10/60/60,10)}:{parseInt(count/10/60%60,10)}
            :{parseInt(count/10%60,10)}.{parseInt(count%10,10)} 초            
            </div>
            <div className="button_wrap">
                <button onClick={startHandler}>Start</button>
                <button onClick={stopHandler}>Stop</button>
                <button onClick={resetHandler}>Reset</button>
            </div>
        </div>
    )
}

시간은 시:분:초 를 표시하며, 소수점 1자리까지(100ms) 초를 표시합니다.

각 버튼을 누를떄마다 위에서 지정한 handler가 실행됩니다.

 

6) 전체 코드

import React, { useRef, useState } from "react";
import './StopWatch.css';

function StopWatch(){
    //ref 객체
    const timeRef = useRef(null);
    //start 작동 여부 판별할 state
    const [isStartOperation,setIsStartOperation]=useState(false);
    //경과 시간 state
    const [count,setCount]=useState(0);
    
    //start 버튼 작동
    const startHandler=()=>{
        //start 작동 안했다면
        if(!isStartOperation){
            //start 작동 체크
            setIsStartOperation(true);
            //ref 객체에 interval 설정 
            timeRef.current = setInterval(()=>{
                //interval에서 count 증가
                setCount((x)=>x+1);
            }
            //100 ms 마다
            ,100
            );
        }
    }

    //정지
    const stopHandler=()=>{
        //start 작동 false 체크
        setIsStartOperation(false);
        //ref 객체에 interval 정지
        clearInterval(timeRef.current);
    }
    //리셋
    const resetHandler=()=>{
        stopHandler();
        setCount(0);
    }

 

    return(
        <div className="stopwatch">
            <div className="stopwatch_title">
                스톱워치
            </div>
            <div className="timer">
            {parseInt(count/10/60/60,10)}:{parseInt(count/10/60%60,10)}
            :{parseInt(count/10%60,10)}.{parseInt(count%10,10)} 초            
            </div>
            <div className="button_wrap">
                <button onClick={startHandler}>Start</button>
                <button onClick={stopHandler}>Stop</button>
                <button onClick={resetHandler}>Reset</button>
            </div>
        </div>
    )
}

export default StopWatch;

 

7) 결과

스톱워치가 잘 작동함을 볼 수 있다.

 

반응형

댓글