react pomodoro timer 리팩토링(1)

웰디(Well-D)·2023년 9월 28일
0

이건 제대로 했던 기억이 나서 처음부터 다시 설계하고 있느라...벌써 5시간 경과! 이렇게 많이 지난 줄도 몰랐다. 사실 3시간만하려고 했는데 인간의 욕심은 끝이없고...

다행히 goal과 round 올리는 것 외에는 일단 타이머 자체는 setTimeout으로 동작이 구현이 완성되었다(제발!)

일단 고친 부분
1. Recoil atoms를 더 간결하게 => 너무 많은 atomState쓰지않도록

  1. useState너무 많이 쓰지 않도록 activate 하나만 가지고 처음 시작, 중간멈춤 , 다시시작 할 수 있게함

  2. setTimeout의 timerId를 통해 제대로 clear할 수 있게 됨 (지난 번에는 chatGPT의 도움을 받아서 겨우겨우 이해해가며 했는데, 이번에는 mdn문서를 보면서 했다)

  3. 지난번에 flag를 하나 더 useState로 해서 중간에 멈추고 다시 재생하는 기능을 어거지로 구현했던(?) 부분이 있는데, 이번에 다시 로직을 짜면서 activate가 true일때는 타이머가 시작하도록 하는 지극히 정상적인 구현을 하게 되었다.

  4. design 폴더 분리하여 컴포넌트로 jsx들을 다 빼주었다. global style도 app에 있으니 너무 지저분해서 분리해주었음

  5. timerId셋팅을 할때 타입스크립트는 그냥 저장이 되지않았는데, window.setTimeout()으로 timerId.current에 저장해야한다. 타입모양 상 그렇다고 하는데 일단 스택오버 플로우에서 확인하여 적용한 결과 구현은 되었음..

  6. timerId 관리를 위해 useRef를 사용해봄
    => 사용이유: 에러메세지에서 권장하고 찾아보니 랜더링과 관계없이 변수를 관리하고 싶을때 사용하는 것, 그리고 타이머를 clear하거나 등에서 많이 쓰인다고 알아보아서 사용

시도했고 적용하지 못한 것들
1. Recoil의 selector을 사용해서 minute과 seconds 간의 관계를 잡아주고 싶었는데, 계산식으로 구현하는 게 생각보다 복잡하기도 하고, 어차피 초기값이 계속해서 셋팅되어야 하는 상황이라 둘다 atoms 로 구현해주었다.

  1. setTimeout => setInterval 로 시도했다가 어차피 시간오차도 있고 이슈도 다양해서 다시 setTimeout으로 돌렸다.

어려웠던 부분들

현상 1 : 두번 눌러야 정지가 풀리는 것
=> render과 관련이 있을 것 같았는데, 전의 로직으로는 제대로 구현이 안되었다. timerId도 로직에 같이 if 문으로 활용하면서 좀 나아짐.

현상 2 : 분만 움직이는 것
=> 중간에 이래저래 고치다가 발견한건데 로직상 loop가 돌지 않아서 그럴듯

현상 3: 들어가자마자 타이머가 자동시작되는 것
=> 이것도 로직문제

현상 4: setTimeout을 재귀로 돌릴때 timerId의 저장방법
=> 나는 화살표함수 const Fn= () => {} 가 익숙해서 이렇게 하다보니 그리고 setTimeout으로 인터벌 구현을 하려면(타이머구현) 재귀함수로 자기자신을 계속 불러와야 한다. 원래 setTimeout함수가 타이머를 위한게 아니라 일정시간이 지날때 함수를 실행시키는 기능이다 보니..
이때 어디에 내부 외부 루프 둘다 timerId를 저장해야하는지, 하나만 저장해야하는지 그리고 이렇게 밖에서 빼준함수를 그냥 넣어주는게 좋은지 아니면 return 값으로 timerId를 만들어서 실행하는 곳에서 ID를 넣어주는게 좋을지 등등....

다양한 고민을 했었음
결과적으로 함수자체에서 내부 외부 둘다 timerId를 넣도록 구현함

수정했던 로직 (최종)

else if (timerId.current !== undefined && activate) {
        setMinutes((prev) => prev - 1);
    } else if (timerId.current === undefined && activate) {
        timerLoop();
    }

setMinutes과 timerLoop가 함께 있었는데 분리했다.
그리고 다른 방식으로 타이머가 시작했을때 25 =? 24가 되게함
위에 있는 else if 구문은 필요 없을것같은데 확인해봐야겠다. => 필요없어서 삭제

더 해야하는 부분들

  1. 지금은 시험삼아 분과 초가 0으로 끝나면 activate(false)로 정지하게 되어있는데 무한으로 돌리기
  2. 1을 하면서 1번마다 goal이 쌓이고 goal 4번마다 round가 쌓이도록 하기
  3. 카드모션

참고한 자료들
Global Styles In React
https://dev-elena-k.tistory.com/41

Uncaught TypeError: Cannot assign to read only property
https://stackoverflow.com/questions/27519836/uncaught-typeerror-cannot-assign-to-read-only-property

Recoil 시작하기
https://recoiljs.org/ko/docs/introduction/getting-started

useRecoilValue(state)
https://recoiljs.org/ko/docs/api-reference/core/useRecoilValue/

setTimeout() global function /setInterval() global function
https://developer.mozilla.org/en-US/docs/Web/API/setTimeout
https://developer.mozilla.org/ko/docs/Web/API/setInterval

[Recoil] Recoil 200% 활용하기
https://velog.io/@juno7803/Recoil-Recoil-200-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0

useResetRecoilState(state)
https://recoiljs.org/ko/docs/api-reference/core/useResetRecoilState/

[React/Typescript] html 태그의 기본 props를 사용해 컴포넌트를 만드는법
https://hackids.tistory.com/133

[JS] setTimeout과 setInterval 차이
https://velog.io/@uiseop/JS-setTimeout%EA%B3%BC-setInterval-%EC%B0%A8%EC%9D%B4

자바스크립트 호출 스케줄링 (setTimeout / setInterval)
https://peach-milk.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%98%B8%EC%B6%9C-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-setTimeout-setInterval

자바스크립트 주기적인 실행(setInterval, setTimeout)
https://offbyone.tistory.com/241

[React] useRef() 는 언제 사용하는가?
https://yoonjong-park.tistory.com/entry/React-useRef-%EB%8A%94-%EC%96%B8%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EA%B0%80

React컴포넌트에서 타이머 설정하기
https://handhand.tistory.com/32

[자바스크립트] 타이머 관련 메소드(setTimeout, clearTimeout, setInterval), 중첩 setTimeout
https://lakelouise.tistory.com/51

profile
Wellness 잘사는 것에 진심인 웰디입니다. 여러분의 몸과 마음, 통장의 건강을 수호하고싶어요. 느리더라도, 꾸준히

0개의 댓글