React를 사용한 카운트다운 타이머

13032 단어 javascriptreacttimer


React의 상태 및 구성 요소 모델의 단점을 탐색하여 시작, 일시 중지, 재개, 중지 및 재설정할 수 있는 카운트다운 타이머를 구축합니다. 아이디어는 간격을 시작하고 참조에서 참조를 추적하는 것입니다. 해당 타이머를 일시 중지할 때 다시 시작할 때 새 타이머를 시작할 수 있는 것과 같은 방식으로 간격을 지울 수 있습니다.


질문은 다음과 같습니다.

사용자가 초 단위로 시간을 입력할 수 있습니다. Start를 클릭하면 기존 타이머가 있으면 취소하고 새로 입력한 시간부터 카운트다운을 시작해야 합니다.

우선 작업을 두 부분으로 나눕니다.
  • 카운트다운 초
  • 초 형식을 hh:mm:ss로 지정

  • 카운트 다운 초



    입력 및 제출 버튼이 있는 양식을 추가해 보겠습니다.

    <form onSubmit={handleStart}>
        <input
            type="number"
            placeholder="Enter total seconds to countdown"
            ref={inputRef}
        />
    
        <button type="submit">Start</button>
    </form>
    


    이렇게 하면 제어되지 않는 필드가 있는 기본 양식이 제공됩니다(사용자가 입력한 값에 대한 상태가 실제로 필요하지 않으므로 괜찮습니다).
    바닐라 React ref인 inputRef도 있습니다. 그것을 정의하자.

    import { useRef } from "react";
    
    export default function App() {
        const inputRef = useRef();
    
        return (
            <form onSubmit={handleStart}>
                <input
                    type="number"
                    placeholder="Enter total seconds to countdown"
                    ref={inputRef}
                />
    
                <button type="submit">Start</button>
            </form>
        )
    }
    


    이제 타이머를 고려해 봅시다. 작동 방식은 0 에 도달할 때까지 카운트를 줄이는 것입니다.
    값을 변경하고 React의 DOM에서 자동으로 업데이트되도록 하는 유일한 방법은 상태를 사용하는 것입니다.
    inputRef 선언 아래에 추가해 보겠습니다.

    // ...
    const inputRef = useRef();
    const [currentTime, setCurrentTime] = useState(0);
    // ...
    


    다음 단계는 실제 카운트다운입니다. setInterval 메서드를 사용하여 매초마다 감소를 실행할 수 있습니다. 이와 함께 구성 요소가 마운트 해제되기 전에 실행 중인 타이머를 지워야 합니다.

    또한 요청에 따라 양식을 제출할 때마다 타이머를 재설정해야 합니다. 따라서 우리는 자신의 재렌더링을 유발하지 않고 재렌더링 전반에 걸쳐 지속되는 timerID에 대한 참조가 필요합니다. 이를 위해 ref 를 사용할 수 있습니다.

    // ...
    const inputRef = useRef();
    const timerRef = useRef();
    const [currentTime, setCurrentTime] = useState(0);
    
    useEffect(() => {
        return () => {
            clearInterval(timerRef.current);
        };
    }, []);
    
    const startTimer = () => {
        timerRef.current = setInterval(() => {
            setCurrentTime((prev) => prev - 1);
        }, 1000);
    }; 
    // ...
    


    여기서 useEffect는 마운트 해제 시 실행되는 정리 함수를 반환합니다. 여기에서 실행 중인 타이머를 정리합니다.
    startTimer 함수는 1000밀리초의 고정 지연으로 타이머를 시작하고 매 틱마다 1씩 감소currentTime하는 역할을 합니다.

    양식 제출 시 트리거되는 get 함수handleStart에서 이 모든 것을 함께 가져와 보겠습니다.

    참고 사항:
  • handleStart 기존 타이머
  • 를 지웁니다.
  • currentTime의 설정값
  • 트리거startTimer

  • // ...
    const handleStart = e => {
        e.preventDefault();
    
        if (timerRef.current) {
          clearInterval(timerRef.current);
        }
    
        const secondsInput = inputRef.current.value;
    
        setCurrentTime(() => secondsInput);
    
        startTimer();
    };
    // ...
    


    여기서 const secondsInput = inputRef.current.value;는 입력의 현재 값을 가져옵니다.

    초 형식을 hh:mm:ss로 지정



    이제 카운터가 감소하므로 hh:mm:ss 로 포맷하는 유틸리티를 추가해 보겠습니다.

    const secondsToHHMMSS = (seconds) => {
      if (seconds < 3600)
        return new Date(seconds * 1000).toISOString().substr(14, 5);
    
      return new Date(seconds * 1000).toISOString().substr(11, 8);
    };
    


    ^는 이 유용한 stackoverflow 답변에서 선택됩니다. https://stackoverflow.com/a/1322771/1939344

    이제 양식 아래에 렌더링해 보겠습니다.

    // ...
    return (
        <div className="App">
            <form onSubmit={handleStart}>
                <input
                type="number"
                placeholder="Enter total seconds to countdown"
                ref={inputRef}
                />
    
                <button type="submit">Start</button>
            </form>
    
            <div className="time">{secondsToHHMMSS(currentTime)}</div>
        </div>
    );
    // ...
    


    완성된 결과:

    좋은 웹페이지 즐겨찾기