여러 개의 state를 useReducer로 관리

송승찬·2020년 10월 2일
0

TIL

목록 보기
42/52

현재 상황

  • 주어진 시간을 시/분/초로 환산 후 1초씩 남은 시간이 줄어드는 타이머가 존재

  • 타이머의 상태 값(state)이 여러개=>(hour,minite,second) 이걸 어떻게 다룰 것인가?

1.useState로 상태값 3개를 관리하는 타이머

timer.js

import React,{useState,useEffect} from 'react';

export default function App () {
    return (
        <Timer  initialTotalSeconds={3373} />
    )
}

function Timer ({initialTotalSeconds}) {
    const [hour,setHour] = useState(Math.floor(initialTotalSeconds/3600));
    const [minutes,setMinutes] = useState(Math.floor((initialTotalSeconds % 3600)/60))
    const [second,setSecond] = useState(initialTotalSeconds % 60)
    useEffect(() => {
        const id = setInterval(()=>{
            if (second) {
                setSecond(second-1)
            } else if (minutes) {
                setMinutes(minutes-1)
                setSecond(59)
            } else {
                setHour(hour-1)
                setMinutes(59)
                setSecond(59)
            }
        },1000)
        return () =>{
            if (second === 59) {
                console.log(hour,second,minutes)
                console.log('id:',id)
            }
            clearInterval(id);
        }
    }, [hour,minutes,second])
    return (
        <div>{hour}시:{minutes}분:{second}초</div>
    )
}

2.위의 코드에 useReducer를 도입

timer-useReducer.js

import React,{useEffect,useReducer} from 'react';

export default function App () {
    return (
        <Timer initialTotalSeconds={3373} />
        )
    }

function Timer ({initialTotalSeconds}) {
    const initialState ={
        hour : Math.floor(initialTotalSeconds/3600),
        minutes : Math.floor((initialTotalSeconds%3600)/60),
        second : Math.floor(initialTotalSeconds%60)
    }
    
    const [state,dispatch] = useReducer(reducer,initialState)
    const {hour,minutes,second} = state
    useEffect(() => {
        const id = setInterval(()=>{
            dispatch()
        },1000);
        return ()=>clearInterval(id)
    })
    return (
        <div style={{margin:'1rem'}}>{hour}시:{minutes}분:{second}초</div>
    )
}

function reducer (state,action) {
    //action은 여기서 실제로는 사용 X, [state,dispatch]의 state를 reducer의 state로 받아서 사용
    const {second,minutes,hour} = state;
    if (second) {
        return {...state,second:second-1}
    } else if (minutes) {
        return {...state,minutes:minutes-1,second:59}
    } else {
        return {...state,hour:hour-1,minutes:59,second:59}
    }
}    

실행 결과


다음과 같은 화면이 출력

profile
superfly

0개의 댓글