ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] 리액트에서 react-moment, moment.js 사용하여 실시간으로 변경되는 시간 만들기
    React 2020. 8. 23. 16:30
    Moment.js는  현재 유지 관리 모드에 있는 레거시 프로젝트입니다. 다른 라이브러리를 사용하시는 것을 추천드립니다. (참고)
    다른 대안 라이브러리 (2023.02.25 수정)

    ✔ moment.js

    • moment.js는 시간이 포함된 데이터를 받아 조작해야 할 경우 가장 많이 사용되는 편리한 라이브러리입니다.
    • 스터디를 모집하는 사이드 프로젝트를 만들 때 사용하였습니다. 현재 시간에 따라서 스터디 신청 마감, 신청중인지 에 따라 실시간으로 변경이 되게 많드는 것이 목표였기 때문에 moment.js를 사용하였습니다.
    • moment.js는 워낙 많이 사용되기 때문에 공식 문서 뿐만 아니라 잘 설명된 블로그들이 많이 존재하기 때문에 moment.js를 사용하는 자세한 방법은 생략하겠습니다.

    🔸 moment 라이브러리 설치

    $ npm i moment
    // 또는
    $ yarn add moment

    🔸 moment 선언

    import moment from 'moment';
    // 안써도 자동으로 한국 시간을 불러온다. 명확하게 하기 위해 import
    import 'moment/locale/ko';

    🔸 현재 시간 가져오기

    // format에 맞게 출력된다.
    const nowTime = moment().format('YYYY-MM-DD HH:mm:ss');
    console.log(nowTime);
    // 출력 결과: 2020-08-23 12:54:30
    • 하지만 현재 상황에서는 현재 상태에서는 현재 시간은 가져오지만, F5키를 눌렀을 때만 시간이 변경됩니다.

    ✌ 리액트 훅스 컴포넌트에서 setInterval 사용 시의 문제점

    • 실시간으로 시간을 변경하기 위해 흔히 사용하는 setInterval을 사용해야 됩니다. 하지만 react Hooks에서 setInterval을 사용했을 때 예상대로 작동하지 않는 문제가 발생합니다.
    • 이 문제에 대한 설명과 그에 대한 해결방법이 자세하게 설명되어 있는 블로그를 참고하시기 바랍니다.
    • 이러한 이유와 성능상의 이슈 때문에 커스텀 Hook을 생성해서 setInterval을 사용할 수 있습니다.
    // useInterval.js 작성
    import { useRef, useEffect } from "react";
    
    export default function useInterval(callback, delay) {
        const savedCallback = useRef();
    
        useEffect(() => {
          // useEffect에 매개변수로 받은 콜백을 현재 Ref로 선언해준다.
          savedCallback.current = callback;
        });
    
        useEffect(() => {
          function tick() {
            savedCallback.current();
          }
            // useEffect에 Ref의 current를 setInterval를 delay 시간동안 해준다.
          let id = setInterval(tick, delay);
          // 언마운트되기전 clearInterval을 해준다.
          return () => clearInterval(id);
        }, [delay]);
      }
    • 📌 다른 방법으로는 많이 사용하는 react-useuseInterval를 사용하면 됩니다.
    import * as React from 'react';
    import {useInterval} from 'react-use';
    
    const Demo = () => {
      const [count, setCount] = React.useState(0);
      const [delay, setDelay] = React.useState(1000);
      const [isRunning, toggleIsRunning] = useBoolean(true);
    
      useInterval(
        () => {
          setCount(count + 1);
        },
        isRunning ? delay : null
      );
    
      return (
        <div>
          <div>
            delay: <input value={delay} onChange={event => setDelay(Number(event.target.value))} />
          </div>
          <h1>count: {count}</h1>
          <div>
            <button onClick={toggleIsRunning}>{isRunning ? 'stop' : 'start'}</button>
          </div>
        </div>
      );
    };

    🔸 useInterval를 사용하여 실시간 시간 사용하기

    import React,{useState}  from 'react';
    
    import moment from 'moment';
    import 'moment/locale/ko';
    import { useInterval } from 'react-use';
    
    const LiveTimeContainer = () => {
      const [realTime, setRealTime] = useState(Date.now());
    
      // useInterval
      useInterval(() => {
        setRealTime(Date.now());
      }, 1000);
    
      return <div>{seconds}</div>
    }
    • 위와 같이 작성하면 실시간으로 moment() 시간을 받아와 별다른 작업없이 시간이 실시간으로 1초마다 변하는 것을 확인할 수 있습니다.

    ✔ react-moment

    • react-moment는 react에서 moment를 편리하게 사용할 수 있게 만들어 놓은 라이브러리입니다.
    • 심지어 react-moment는 별다른 작업을 하지않아도 실시간으로 시간이 변하게 제공을 해줍니다.
    • 📌 react-moment의 자세한 설명은 공식 문서를 참고해주세요.

    🔸 react-moment 라이브러리 설치

    • react-moment는 moment가 dependency되어 있기 때문에 moment 부터 설치해주어야 합니다.
    $ npm i moment react-moment
    // yarn
    $ yarn add moment react-moment
    // moment-timezone을 사용할려면
    $ npm i moment-timezone
    • 아래 사진은 사이드 프로젝트를 만들 때 세로고침을 하지 않아도 자동으로 시간이 변하여 접수가 열리고 접수중으로 상태가 변하고 대회도 마찬가지로 접수가 마감되고 대회시작의 상태를 알려주도록 구현하기 위해서 react-moment를 사용하였습니다.

    🔸 react-moment 선언하고 기본 익히기

    import React  from 'react';
    import Moment from 'react-moment';
    
    const MomentDateChage = () => {
      const nowTime = Date.now();
      // Sun Aug 23 2020 15:43:49 GMT+0900
      return <Moment>{nowTime}</Moment>;
    }
    • 기본적으로 react-moment는 60초(60000 milliseconds)로 interval을 합니다. 하지만 interval을 수정하여 사용할 수 있고 굳이 필요없는 곳에는 intervaldisable시킬 수 있습니다.
    import React  from 'react';
    import Moment from 'react-moment';
    
    const MomentDateChage = () => {
      const nowTime = Date.now();
      // interval 30초
      //return <Moment interval = { 30000 }>{nowTime}</Moment>;
      // interval disable
      return <Moment interval = { 0 }>{nowTime}</Moment>;
    }
    • 현재 날짜에서 주어진 시간에 얼마나 지나거나 얼마나 남았는지를 알려줍니다.
    • 이렇게 적용해주면 5분 후 또는 몇초 후, 몇일 후로 나오게 되는데 만약 영어로 나올 경우는 아래와 같이 적용해줍니다.
    import React  from 'react';
    import Moment from 'react-moment';
    import 'moment/locale/ko';
    
    const MomentDateChage = () => {
      const nowTime = Date.now(),
            startTime = new Date("2020-08-23T16:00");
    
      return <Moment fromNow>{startTime}</Moment>;
    }
    • 더 많은 기능들은 공식문서를 참고하거나 블로그를 참고하시기 바랍니다.

    ✌ react-moment와 moment를 사용하여 응용해보기

    • 마지막으로 몇분 후 접수 시작이라고 나온뒤 접수 신청 시간이 되면 새로고침 없이 접수중으로 변경해보겠습니다.
    • momentuseInterval를 사용하여 현재 시간을 불러오고, react-moment로 자동으로 시간이 변경되게 사용합니다.

    • 아래는 간단한 예시입니다.
    import React,{useState}  from 'react';
    
    import moment from 'moment';
    import Moment from 'react-moment';
    import 'moment/locale/ko';
    
    import { useInterval } from 'react-use';
    
    const LiveTimeContainer = () => {
      const [seconds, setSeconds] = useState(Date.now());
    
      // useInterval
      useInterval(() => {
        setSeconds(Date.now());
      }, 1000);
    
      const startTime = new Date('2020-08-23T16:09'),
            nowTimeFormat = new Date(seconds);
    
      return (
          <>
        {startTime - nowTimeFormat > 0 ? 
         (<><Moment fromNow>{startTime}</Moment>&nbsp;접수 시작</>) : (<div>{'접수 중'}</div>)
        }  
        </>
      )
    }

    📌 스터디 모집 사이트 소스를 확인해보고 싶으면 Github를 확인하시기 바랍니다.

    StudyGroupsContainer.jsx

    DateTimeChange.jsx

    IntroduceForm.jsx

     

    😃 또한, 수정해야할 정보나 부분이 있으면 댓글로 피드백 부탁드립니다. 🙏

    댓글

Designed by Seungmin Sa.