사용자 정의 갈고리를 사용하여 React JS에서 스톱워치를 개발하는 방법

사물이 어떻게 일을 하는지 진정으로 이해하기 위해서 우리는 임무를 더욱 작은 부분으로 분해해야 한다. 이것이 바로 우리가 여기서 한 일이다.우리의 최종 목표는 React 원생 Pomodoro 시계 응용 프로그램을 구축하는 것이다. 그러나 우선, 우리는 setIntervalclearInterval가 React with hooks에서 어떻게 작동하는지 알고 이 시계를 Pomodoro 시계로 전환할 것이다.

시작합시다.


먼저 모든 내용을 분해하고 견본을 구축합시다.
import React, { useState } from 'react';
import './App.css';

const App = () => {
  const [timer, setTimer] = useState(0)
  const [isActive, setIsActive] = useState(false)
  const [isPaused, setIsPaused] = useState(false)
  const countRef = useRef(null)

  const handleStart = () => {
    // start button logic here
  }

  const handlePause = () => {
    // Pause button logic here
  }

  const handleResume = () => {
    // Resume button logic here
  }

  const handleReset = () => {
    // Reset button logic here
  }

  return (
    <div className="app">
      <h3>React Stopwatch</h3>
      <div className='stopwatch-card'>
        <p>{timer}</p> {/* here we will show timer */}
        <div className='buttons'>
          <button onClick={handleStart}>Start</button>
          <button onClick={handlePause}>Pause</button>
          <button onClick={handleResume}>Resume</button>
          <button onClick={handleReset}>Reset</button>
        </div>
      </div>
    </div>
  );
}

export default App;
시작 버튼을 클릭하면 타이머가 0부터 시작됩니다.isActive 타이머가 활성 상태인지 확인하는 것으로 정의됩니다.isPaused 타이머가 일시 중지되었는지 확인하는 것으로 정의됩니다.
처음에 두 값은 모두 false 였다.이 값을 정의하여 시작, 일시 중지 및 복구 버튼을 조건부로 렌더링합니다.

UseRef 갈고리

useRef 원소의 인용을 얻거나 제어하는 데 도움을 줍니다.
이것은 우리가 사용한 document.getElementById("demo") vanillajavascript에서 얻은 참고와 같다. 이것은 우리가 가상dom를 건너뛰고 브라우저를 직접 처리했다는 것을 의미한다.useRef갈고리가 강하지 않나요?
만약 우리가 이 코드를 실행한다면, 우리는 이러한 결과를 볼 수 있을 것이다.(CSS는 본문의 끝에 포함되어 있습니다)

지금 우리는 세 가지 임무를 해야 하는데,
  • 버튼당 함수 작성
  • 우리가 초시계(00:00)에서 본 방식에 따라 타이머를 포맷한다
  • 조건부 표시 버튼
  • 기능 시작


    시작 기능의 역할은 타이머를 시작하고 우리가 리셋하거나 멈출 때까지 계속 증가하는 것이다.
    이를 위해 우리는 setInterval 방법을 사용할 것이다.setInterval 우리가 그것을 막지 않는다면.그것은 두 개의 매개 변수가 필요하다.콜백 및 시간 (ms) 입니다.setInterval(func, time) 1000 ms = 1 second
    const handleStart = () => {
      setIsActive(true)
      setIsPaused(true)
      countRef.current = setInterval(() => {
        setTimer((timer) => timer + 1)
      }, 1000)
    }
    
    일단 시작 단추를 누르면 isActiveisPausedtrue 으로 바뀌고 초당 타이머 값에 1을 추가합니다.
    우리는 countRefcurrent 속성을 setInterval 함수로 설정합니다. 이것은 변수 countRef 에 timerId를 설정한 것을 의미합니다. 현재 우리는 다른 함수에서 그것을 사용할 수 있습니다.
    참조된 현재 값은 countRef.current를 사용합니다.

    일시 중지 기능

    setInterval 호출할 때까지 자신을 호출한다clearInterval.
    계수기를 멈추거나 멈추기 위해서는 clearInterval 기능을 사용해야 합니다.clearInterval은 id 매개 변수가 필요합니다. countRef.current 방법의 매개 변수로 전달할 것입니다.
    const handlePause = () => {
      clearInterval(countRef.current)
      setIsPaused(false)
    }
    
    일시 중지 버튼을 누르면 타이머를 중지(재설정하지 않음)하고 clearInterval 상태를 isPaused 에서 true 로 변경합니다.

    복구 기능


    const handleResume = () => {
      setIsPaused(true)
      countRef.current = setInterval(() => {
        setTimer((timer) => timer + 1)
      }, 1000)
    }
    
    타이머를 복구하면 일시 중지된 위치에서 타이머를 시작하고 false 에서 isPaused 로 변경합니다.

    기능 재설정


    const handleReset = () => {
      clearInterval(countRef.current)
      setIsActive(false)
      setIsPaused(false)
      setTimer(0)
    }
    
    재설정 함수는 모든 내용을 초기 값으로 재설정합니다.이 단추는 계수기를 멈출 뿐만 아니라 값을 0으로 초기화합니다.

    렌더 버튼 로직


    시작, 일시 중지 및 복구 버튼 렌더링 논리에 대해 논의합니다.
    타이머가 시작되면 falsetrue 로 바뀌고, 타이머를 멈추면 start button 을 볼 수 있습니다.이것이 바로 초시계의 작업 원리이다. 아니면 우리가 그것이 어떻게 작동하기를 바란다고 말할 수 있다.
    우리는 어떤 단추를 표시해야 하는지 어떻게 알았습니까?
    이를 위해, 우리는 이미 우리의 상태에서 두 개의 키를 정의했다.하나는 Pause, 다른 하나는 Resume button그것들은 처음에는 모두 가짜였다.
    두 키가 모두false라면, 시작 단추를 표시합니다.이것은 명백히 알 수 있다.
    멈출 때 무슨 일이 일어날까요?
    isActive는 true, isPaused는 false
    그렇지 않으면 복구 단추가 표시됩니다.
    우리는 중첩 isActive 조건을 작성해야 한다.시작 또는 일시 중지/복구 버튼이 표시됩니다.

    타이머 포맷


    응용 프로그램의 또 다른 까다로운 부분은 이런 방식으로 타이머를 표시하는 것이다isPaused몇 초 동안 지속되다
    const getSeconds = `0${(timer % 60)}`.slice(-2)
    
    몇 분
     const minutes = `${Math.floor(timer / 60)}`
     const getMinutes = `0${minutes % 60}`.slice(-2)
    
    몇 시간 동안 지속되다
    const getHours = `0${Math.floor(timer / 3600)}`.slice(-2)
    
    우리는 이를 위해 if else 함수를 만들고 초, 분, 시간을 되돌려줍니다.
      const formatTime = () => {
        const getSeconds = `0${(timer % 60)}`.slice(-2)
        const minutes = `${Math.floor(timer / 60)}`
        const getMinutes = `0${minutes % 60}`.slice(-2)
        const getHours = `0${Math.floor(timer / 3600)}`.slice(-2)
    
        return `${getHours} : ${getMinutes} : ${getSeconds}`
      }
    
    react에서 단추는 00:00:00 도구를 가지고 있으며, 기본적으로false입니다. 논리를 추가해서 실현할 수 있습니다.단순 논리 formatTime 만 추가하여 타이머를 0으로 설정하면 재설정 단추가 비활성화됩니다.

    지금까지 완전한 코드


    import React, { useState, useRef } from 'react';
    import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
    import { faClock } from '@fortawesome/free-regular-svg-icons'
    
    import './App.css';
    
    const element = <FontAwesomeIcon icon={faClock} />
    
    const App = () => {
      const [timer, setTimer] = useState(3595)
      const [isActive, setIsActive] = useState(false)
      const [isPaused, setIsPaused] = useState(false)
      const increment = useRef(null)
    
      const handleStart = () => {
        setIsActive(true)
        setIsPaused(true)
        increment.current = setInterval(() => {
          setTimer((timer) => timer + 1)
        }, 1000)
      }
    
      const handlePause = () => {
        clearInterval(increment.current)
        setIsPaused(false)
      }
    
      const handleResume = () => {
        setIsPaused(true)
        increment.current = setInterval(() => {
          setTimer((timer) => timer + 1)
        }, 1000)
      }
    
      const handleReset = () => {
        clearInterval(increment.current)
        setIsActive(false)
        setIsPaused(false)
        setTimer(0)
      }
    
      const formatTime = () => {
        const getSeconds = `0${(timer % 60)}`.slice(-2)
        const minutes = `${Math.floor(timer / 60)}`
        const getMinutes = `0${minutes % 60}`.slice(-2)
        const getHours = `0${Math.floor(timer / 3600)}`.slice(-2)
    
        return `${getHours} : ${getMinutes} : ${getSeconds}`
      }
    
      return (
        <div className="app">
          <h3>React Stopwatch {element}</h3>
          <div className='stopwatch-card'>
            <p>{formatTime()}</p>
            <div className='buttons'>
              {
                !isActive && !isPaused ?
                  <button onClick={handleStart}>Start</button>
                  : (
                    isPaused ? <button onClick={handlePause}>Pause</button> :
                      <button onClick={handleResume}>Resume</button>
                  )
              }
              <button onClick={handleReset} disabled={!isActive}>Reset</button>
            </div>
          </div>
        </div>
      );
    }
    
    export default App;
    

    코드 정리하래요.


    나는 우리가 상태와 방법을 사용자 정의 연결에서 추출할 수 있다는 것을 깨달았다.이것은 우리의 코드를 깨끗하고 다시 사용할 수 있게 할 것이다.

    useTimer 연결

    disabled 폴더에서 나는 또 하나의 폴더disabled={!isActive}를 만들었고,hook에서 나는 하나의 파일을 만들었다srcuseTimer 갈고리는 우리의 상태와 네 개의 함수를 되돌려줍니다.현재, 우리는 우리의 응용 프로그램에서 언제 어디서나 그것을 사용할 수 있다.
    import { useState, useRef } from 'react';
    
    const useTimer = (initialState = 0) => {
      const [timer, setTimer] = useState(initialState)
      const [isActive, setIsActive] = useState(false)
      const [isPaused, setIsPaused] = useState(false)
      const countRef = useRef(null)
    
      const handleStart = () => {
        setIsActive(true)
        setIsPaused(true)
        countRef.current = setInterval(() => {
          setTimer((timer) => timer + 1)
        }, 1000)
      }
    
      const handlePause = () => {
        clearInterval(countRef.current)
        setIsPaused(false)
      }
    
      const handleResume = () => {
        setIsPaused(true)
        countRef.current = setInterval(() => {
          setTimer((timer) => timer + 1)
        }, 1000)
      }
    
      const handleReset = () => {
        clearInterval(countRef.current)
        setIsActive(false)
        setIsPaused(false)
        setTimer(0)
      }
    
      return { timer, isActive, isPaused, handleStart, handlePause, handleResume, handleReset }
    }
    
    export default useTimer
    

    UTIL


    우리는 vanillajavascript 함수를utils 폴더에 써서 코드를 더욱 간결하게 할 수 있습니다.
    이를 위해 hook 폴더를 만들었고, 유틸리티에서 useTimer.js 파일을 만들었습니다.
    export const formatTime = (timer) => {
      const getSeconds = `0${(timer % 60)}`.slice(-2)
      const minutes = `${Math.floor(timer / 60)}`
      const getMinutes = `0${minutes % 60}`.slice(-2)
      const getHours = `0${Math.floor(timer / 3600)}`.slice(-2)
    
      return `${getHours} : ${getMinutes} : ${getSeconds}`
    }
    

    타이머회사 명


    코드를 src 에서 utils 로 복사하고 index.js 내부 렌더링App.js이것이 바로 우리의 폴더 구조이다

    import React from 'react';
    import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
    import { faClock } from '@fortawesome/free-regular-svg-icons'
    
    import useTimer from '../hooks/useTimer';
    import { formatTime } from '../utils';
    
    const element = <FontAwesomeIcon icon={faClock} />
    
    const Timer = () => {
      const { timer, isActive, isPaused, handleStart, handlePause, handleResume, handleReset } = useTimer(0)
    
      return (
        <div className="app">
          <h3>React Stopwatch {element}</h3>
          <div className='stopwatch-card'>
            <p>{formatTime(timer)}</p>
            <div className='buttons'>
              {
                !isActive && !isPaused ?
                  <button onClick={handleStart}>Start</button>
                  : (
                    isPaused ? <button onClick={handlePause}>Pause</button> :
                      <button onClick={handleResume}>Resume</button>
                  )
              }
              <button onClick={handleReset} disabled={!isActive}>Reset</button>
            </div>
          </div>
        </div>
      );
    }
    
    export default Timer;
    
    이제 더 깨끗해 보이지 않나요?
    CSS
    @import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@500&display=swap");
    
    body {
      margin: 0;
      font-family: "Quicksand", sans-serif;
      background-color: #eceff1;
      color: #010b40;
    }
    
    .app {
      background-color: #0e4d92;
      margin: 0 auto;
      width: 300px;
      height: 200px;
      position: relative;
      border-radius: 10px;
    }
    
    h3 {
      color: white;
      text-align: center;
      padding-top: 8px;
      letter-spacing: 1.2px;
      font-weight: 500;
    }
    
    p {
      font-size: 28px;
    }
    
    .stopwatch-card {
      position: absolute;
      text-align: center;
      background-color: white;
      box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
      width: 325px;
      height: 130px;
      top: 110px;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
    button {
      outline: none;
      background: transparent;
      border: 1px solid blue;
      padding: 5px 10px;
      border-radius: 7px;
      color: blue;
      cursor: pointer;
    }
    
    .buttons {
      display: flex;
      justify-content: space-evenly;
      width: 150px;
      margin: 0 auto;
      margin-top: 5px;
    }
    
    만약 당신이 다음 typescript에 관한 글을 읽고 싶다면, 피드백이 필요합니까?
    typescript가 발전하고 있기 때문에, 초창기 회사는 typescript로 자바스크립트를 입력할 수 있는 사람들을 더욱 좋아한다.
    다음 부분에서, 우리는 이 프로그램을 Pomodoro 시계로 바꿀 것이다.
    Codepen 데모

    좋은 웹페이지 즐겨찾기