-
[React Hooks] 회원가입 인증번호 타이머 구현Front-end/React.js 2020. 5. 30. 00:45
회원가입/패스워드 찾기를 진행할 때 반드시 필요한 것이 인증번호다. (이메일이든 전화번호든)
API를 호출하여 인증번호를 생성할 때는 인증번호의 유효기간이 존재한다.
처음에 타이머를 구현할 때는 유효기간인 3분을 초기값으로 정해놨지만
그렇게 짜면 새로고침을 할 때마다 유효기간이 3분으로 늘어난다는 버그가 있었다.
그래서 Redux와 React Hooks를 이용하여 유효기간을 display하는 컴포넌트를 작성했다.
import React, { useEffect, useState } from 'react' import { useSelector } from 'react-redux' import { RootState } from '../../modules' const AuthTimer = () => { // code } export default AuthTimer
React hooks를 이용하려면 Functional 컴포넌트로 작성해야 한다.
const [time, setTime] = useState(179) const { verification } = useSelector((state: RootState) => state.auth) const { expireAt } = verification.OTP
useState를 이용해서 초기값을 179로 했다. 유효기간이 3분인데 초 단위로 넣는다.
180이 아닌 이유는 유효기간을 받아오는 순간 사실 3분이 될 수가 없기 때문에 179로 넣었다.
redux에 state로 저장된 expireAt을 가져온다.
useEffect(() => { if (time > 0) { const Counter = setInterval(() => { const gap = Math.floor((new Date(expireAt).getTime() - new Date().getTime()) / 1000) setTime(gap) }, 1000) return () => clearInterval(Counter) } }, [expireAt, time])
setInterval 함수를 이용해서 1000ms마다 익명함수를 실행시키는 코드를 작성했다.
단 useEffect로 time의 state를 변경시킬 때마다 리렌더링이 일어나므로 계속 clearInterval을 해주어야 버그가 안난다.
시간 차는 Date 인스턴스를 이용해서 ms 단위로 number 데이터를 구해 1000으로 나누고 Math.floor로 내림했다.
이렇게 하면 초 단위로 1초씩 줄어드는 데이터를 생성할 수 있다. 단 포맷에 맞게 디스플레이할 수 있도록 포맷 함수를 만들었다.
const timeFormat = (time: number) => { const m = Math.floor(time / 60).toString() let s = (time % 60).toString() if (s.length === 1) s = `0${s}` return `${m}:${s}` }
mm:ss 형태로 렌더링하고자 timeFormat을 작성했다.
import React, { useEffect, useState } from 'react' import { useSelector } from 'react-redux' import { RootState } from '../../modules' const AuthTimer = () => { const [time, setTime] = useState(179) const { verification } = useSelector((state: RootState) => state.auth) const { expireAt } = verification.OTP useEffect(() => { if (time > 0) { const Counter = setInterval(() => { const gap = Math.floor((new Date(expireAt).getTime() - new Date().getTime()) / 1000) setTime(gap) }, 1000) return () => clearInterval(Counter) } }, [expireAt, time]) const timeFormat = (time: number) => { const m = Math.floor(time / 60).toString() let s = (time % 60).toString() if (s.length === 1) s = `0${s}` return `${m}:${s}` } return ( <> <p style={{ textAlign: 'right', fontSize: '14px', color: '#ff5252', position: 'absolute', right: '92px', bottom: '14px', letterSpacing: '-0.4px' }} > {timeFormat(time)} </p> </> ) } export default AuthTimer
최종 코드는 위와 같다.
프로젝트마다 다르긴 하겠지만 인증번호가 생성된 경우에만 타이머가 렌더링되도록 Join 컴포넌트에 TSX로 작성했다.
타입스크립트 프로젝트에서 만든 컴포넌트여서 ts 파일로도 사용 가능하다.
참고 링크 : https://dev.to/zhiyueyi/how-to-create-a-simple-react-countdown-timer-4mc3
'Front-end > React.js' 카테고리의 다른 글
React-Admin Modal 컴포넌트 사용 (0) 2020.04.29 [React.js] React로 Google Map Reverse Geocoding하기 (0) 2020.04.09 React Hook이란? - useState (0) 2020.04.01 📒 React Document 메모 (0) 2020.03.12 react-admin : <Show> View (0) 2020.03.04