useInterval을 또 다시 사용해보자

YEONGHUN KO·2022년 6월 21일
1

REACT JS - PRACTICE

목록 보기
6/15
post-thumbnail
post-custom-banner

이전 포스트에서 만들었던 useInterval을 이용해서 시간이 얼마나 남았는지 출력하는 앱을 만들어보려고 한다. 2탄이다!!

들어가기에 앞서 이번 글도 코드종님의 영상을 참고하여 정리하는 글이다.
코좀봐코

앱을 만들기 전에 항상 생각해야할것은 입력출력이다. 리액트 훅을 이용한 함수 컴포넌트는 기본적으로 순수함수이다.

순수함수의 출력값을 바꾸는 것은 입력값밖에 없다. 입력값은 prop, state가 대표적이다.

그래서 입력값을 생각해보자. 얼마나 남았는 지 가 입력이 되고 출력은 말그대로 그 입력을 그대로 출력하면 된다. 이런식으로 입력과 출력을 생각하면 사고의 흐름이 명확해진다.

그럼 일단 prop을 통해 넘겨주는 방식으로 만들어 보자

const App = ()=>{
  const targetISOString = '2022-01-01T09:00:00.000Z';//한국 시간 기준 2022년 시작 시간
  const calculator = () => Math.floor((new Date(targetISOString) - new Date())/1000);
  const [remain, setRemain] = useState(calculator());
  
  useInterval(()=>{
  	setRemain(calculator());
  }, 100); //일단, 세밀한 업데이트를 위한 100ms으로
  return (
  <div>
     <Nav/>
     <CountDownView remain={remain}/>
  </div>
  )
}

일단 동작은 잘한다. 근데 그다지 좋은 방법은 아니다. 왜냐면 App 전체가 랜더링 되기 때문에 countDownView뿐만 아니라 Nav컴포넌트까지 쓸데없이 랜더링 된다.

이때 생각해야하는 것이 sepration of concern 즉, 관심도를 분리하여 응집도를 높이는 것이다. 관심분리를 통한 응집도 향상을 항상 신경쓰자!!!

그럼 아래와 같이 코드를 짤 수 있다.

const CountDownView = ({ targetISOString }) => {
  const calculator = () => Math.floor((new Date(targetISOString) - new Date())/1000);

  const [remain, setRemain] = useState(calculator());
  useInterval(()=>{
  	setRemain(calculator());
  }, 100);
  
  return (
    <div>
      남은 시간 : {remain} 
    </div>
  );
};

App에선 기준이 되는 시점만 넘겨주고 계산은 CountDownView에서 처리한다. 근데 여기서 더 리팩토링 할 수 있다. useResultOfIntervalCalculator 를 만드는 것이다.

const useResultOfIntervalCalculator = (calculator, delay) => {
  const [result, setResult] = useState(calculator());
  useInterval(() => {
    const newResult = calculator();
    if (newResult !== result) setResult(newResult);
  }, delay);

  return result;
};


const CountDownView = ({ targetISOString }) => {
  const remain = useResultOfIntervalCalculator(() =>
    Math.floor((new Date(targetISOString) - new Date()) / 1000, 10)
  );
  return <div className="CountDownWrap">남은 시간 : {remain}</div>;
};

export default function App() {
  const targetISOString = "2022-06-21T09:00:00.000Z";

  const isNotYet = useResultOfIntervalCalculator(
    () => new Date(targetISOString) - new Date() > 0,
    10
  );
  return (
    <div className="App">
      <Nav />
      <CountDownView targetISOString={targetISOString} />
      {isNotYet ? "기다리세요." : "이미 지났습니다."}
      
    </div>
  );
}

useResultOfIntervalCalculator에 매번 계산이 되어야할 수식을caculator로 넘겨주면 계산된 값을 useInterval을 통해 지속적으로 넘겨준다.

이로써 관심 분리, 순수함수에 대한 개념을 다시 정립할 수 있었고 custom hook에 대해서도 더 가까워진것 같다.

출처:
1. https://class.codejong.kr/t/react/371/3
2. https://www.youtube.com/watch?v=zBmTqF0GpN4

profile
'과연 이게 최선일까?' 끊임없이 생각하기
post-custom-banner

0개의 댓글