react 카운트다운 반복 재실행에 대해 질문드립니다.

주기적으로 끝나고 다시 실행되는 카운트다운 2개를 만들어야하는데 하나가 일찍 끝나면 나머지 하나가 일찍끝난거와 동시에 다시 재시작 되어 버리네요 두 컴포넌트의 연관성이 전혀 없는거 같은데 영향받는게 이해가 안가 질문드립니다… 도와 주세요!
TimerM1.js

import { useEffect, useState } from "react";
import { useInterval } from "./hooks";
import { useDispatch } from "react-redux";
import { pickWinnerAction } from "../../redux/actions/pickWinnerAction";

const useResultOfIntervalCalculator = (calculator, delay) => {
    const dispatch = useDispatch();
    const [result, setResult] = useState(calculator());
    useInterval(() => {
      const newResult = calculator();
      if (newResult !== result) setResult(newResult);
    }, delay);
    if(result === 1) {
    //   dispatch(pickWinnerAction.pickWinnerAct());
    }
    return result;
  };
  
  const CountDownView = ({ targetISOString }) => {
    const remain = useResultOfIntervalCalculator(() =>
      Math.floor((new Date(targetISOString) - new Date()) / 1000, 10)
    );

    var hour = parseInt((remain / 3600));
    var min = parseInt((remain % 3600) / 60);
    var sec = remain % 60;
    return <div className="CountDownWrap"><p>MODE#1 Remain</p><p>{hour} H {min} M {sec} S</p></div>;
  };

const TimerM1 = () => {
    const [targetISOString, setTargetISOString] = useState("11 17 2022 16:40:00");
    const isNotYet = useResultOfIntervalCalculator(
      () => new Date(targetISOString) - new Date() > 0, 10
    );

    const test = () => {
        return new Date(targetISOString) - new Date()
      }
      const test2 = useResultOfIntervalCalculator(test, 1000);
  
    const ChangeTimer = () => {
        const crt = new Date()
        const year = crt.getFullYear();
        const month = crt.getMonth();
        const date = crt.getDate();
      const hour = crt.getHours();
      const minutes = crt.getMinutes();
      if(!isNotYet) {
        if(minutes + 1 < 60)
        setTargetISOString(`${month + 1} ${date} ${year} ${hour}:${minutes + 2}:00 `)
        else if(minutes + 1 === 60 && hour + 1 < 24)
        setTargetISOString(`${month + 1} ${date} ${year} ${hour + 1}:00:00 `)
        else if(minutes + 1 === 60 && hour + 1 === 24)
        setTargetISOString(`${month + 1} ${date + 1} ${year} 00:00:00 `)
      }
    }

    useEffect(() => {
      ChangeTimer();
    },[isNotYet])


    return (
      <div>
        <CountDownView targetISOString={targetISOString} />
      </div>
    );
}

export default TimerM1

TimerM2.js

import { useEffect, useState } from "react";
import { useInterval } from "./hooks";
import { useDispatch, useSelector } from "react-redux";
import { pickWinnerM2Action } from "../../redux/actions/pickWinnerM2Action";

const useResultOfIntervalCalculatorM2 = (calculator, delay) => {
    const dispatch = useDispatch();
    const [resultM2, setResultM2] = useState(calculator());
    useInterval(() => {
      const newResultM2 = calculator();
      if (newResultM2 !== resultM2) setResultM2(newResultM2);
    }, delay);
    if(resultM2 === 1) {
      // dispatch(pickWinnerM2Action.pickWinnerM2Act());
    } 
    return resultM2;
  };
  
  const CountDownViewM2 = ({ targetISOStringM2 }) => {
    const remain = useResultOfIntervalCalculatorM2(() =>
      Math.floor((new Date(targetISOStringM2) - new Date()) / 1000, 10)
    );
    var hour = parseInt((remain / 3600));
    var min = parseInt((remain % 3600) / 60);
    var sec = remain % 60;
    return <div className="CountDownWrap"><p>MODE#2 Remain</p><p>{hour} H {min} M {sec} S</p></div>;
  };

const TimerM2 = () => {
  const dispatch = useDispatch();
  const [targetISOStringM2, setTargetISOStringM2] = useState("11 17 2022 15:21:00");
  const isNotYetM2 = useResultOfIntervalCalculatorM2(
      () => new Date(targetISOStringM2) - new Date() > 0, 10
    );
    const ChangeTimerM2 = () => {
      const crt = new Date()
      const year = crt.getFullYear();
      const month = crt.getMonth();
      const date = crt.getDate();
    const hour = crt.getHours();
    const minutes = crt.getMinutes();
    if(!isNotYetM2) {
      if(minutes + 1 < 60)
        setTargetISOStringM2(`${month + 1} ${date} ${year} ${hour}:${minutes + 1}:00 `)
        else if(minutes + 1 === 60 && hour + 1 < 24)
        setTargetISOStringM2(`${month + 1} ${date} ${year} ${hour + 1}:00:00 `)
        else if(minutes + 1 === 60 && hour + 1 === 24)
        setTargetISOStringM2(`${month + 1} ${date + 1} ${year} 00:00:00 `)
      }
    }

    useEffect(() => {
      ChangeTimerM2();
    },[isNotYetM2])


    return (
      <div>
        <CountDownViewM2 targetISOStringM2={targetISOStringM2} />
      </div>
    );
}

export default TimerM2

hooks.js

import { useEffect, useRef } from "react";

export function useInterval(callback, delay) {
  const savedCallback = useRef();
  // console.log(savedCallback.current)

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}```

안녕하세요~ https://codepen.io 같은 곳에 문제가 재현되게 올려주실 수 있나요?

일단 질문에 해당하는 내용은 아니지만 react 관련 피드백 드리자면

  • 리액트 컴포넌트 함수는 대문자로 시작합니다. 그렇다보니 리액트 컴포넌트가 아닌 일반 함수의 경우 소문자로 시작해주세요.(ChangeTimerM2 → changeTimerM2)
  • Date를 다루실 때 day.js 를 사용하면 편리합니다.