티스토리 뷰

 

*피드백은 언제나 환영합니다🙌

 

 

지난 글에서는 라우터로 컴포넌트별 경로를 설정했었다. 이번 글에서는 시계를 만드는 과정을 다루려고 한다.

 

내가 원하는 시계 기능은 이렇다.

  • 오전, 오후 표시될 것
  • 시, 분, 초 표시될 것
  • 1초마다 시간 갱신

 

먼저 현재 시간을 얻기 위해 new Date()를 사용했다. 예전에 바닐라 자바스크립트 공부할 때 배웠었는데... 기억이 새록새록..

그땐 블로그를 하거나 어딘가에 기록하진 않았었다.

 

하지만 꼭 블로그 해보라고 추천하고 싶다. 내가 단순히 이해하는 거랑 말로 풀어서 설명하는 건 또 다른 느낌이라 쉽지않다.. 그만큼 내 것으로 만들어지는 것 같아 좋기도 하고😀

 

 

이제 진짜 시계만들기 시작!

우선 new Date()를 state에 저장했다.

let [time, setTime] = useState(new Date())

 

그리고 데이터 바인딩 해주었다.

<div className='nowTime'>
	{time}
</div>

 

근데 Uncaught Error: Objects are not valid as a React child (found: [object Date]). If you meant to render a collection of children, use an array instead. 이라는 에러가 떴다.

 

구글링 해보니 스택 오버플로우에 나랑 비슷한 질문을 하신 분이 계셨다.

▶ 답변: 리액트에서는 Date나 Arrays와 같은 객체를 자식으로 허용하지 않는다. 따라서 String으로 변경해주어야 한다.

 

 

무슨 말인지 대충 알겠는데.. 좀 더 명확한 답변을 찾고 싶어 구글링을 해봤다.

찾아보니 JSX 코드에선 객체나 배열이 렌더링되지 않기 때문에 문자열이나 숫자와 같은 원시 값을 렌더링 해야한다고 한다. 또 Date는 JSX 코드에서 직접 렌더링하면 오류가 발생하기 때문에 Date에 메소드를 사용해야 한다고 한다.

 

실제로 콘솔창에 typeof new Date()를 해봤더니 object가 떴다.

오.. JSX 에서는 객체, 배열을 데이터바인딩 하면 오류가 뜨는구나

새로운걸 알게됐다.

 

그래서 toLocaleTimeString() 메소드를 이용해 object를 string으로 변환해주었다.

toLocaleTimeString() 메소드는 현재 내가 있는 지역의 시간을 표시해 준다.

 

<div className='nowTime'>
	{time.toLocaleTimeString()}
</div>

 

 

창을 새로고침 하니 현재 시간이 떴다. 근데 시간이 갱신이 안 된 채로 멈춰 있다.

 

 

왼쪽 네비게이션 바

 

 

 

검색해보니 setInterval을 사용하라고 한다.

setInterval은 일정 시간 간격으로 함수를 실행해준다.
문법은 setInterval(함수명, interval간격)이다.

그래서 현재 시간을 뜨게 하려면 1초 간격으로 new Date()를 실행시키면 된다.

 

먼저 useEffect를 통해 로드 시 한 번 만 setInterval이 동작하도록 했다. (두번째 인자를 빈배열로 만듦) 그리고 1초마다 시간을 불러오도록 코드를 짰다.

useEffect(()=>{
const timer = setInterval(() => {
  setTime(new Date());
}, 1000);
return ()=>{
clearInterval(timer)
}
}, []);

 

근데 궁금한게 검색해보면 setInterval 쓸 때 useEffect 쓰라고 하는데 왜일까? useEffect 밖에 적어도 똑같이 실행되는데...?

그럼.. 안적어도 되는거 아냐?!

 

 

useEffect 쓰는 이유가 뭘까?


Q. useEffect 밖에 적어도 똑같은데?

 

A. useEffect 안에 적은 코드는 html 렌더링 이후에 동작한다.

예를들어 굉장히 시간이 오래걸리는 쓸데없는 코드가 필요하다고 가정해보자.

function Detail(){

  (반복문 10억번 돌리는 코드)
  return (생략)
}

여기에 적으면 반복문을 돌리고 나서 하단의 html을 보여준다.

 

function Detail(){

  useEffect(()=>{
    (반복문 10억번 돌리는 코드)
  });
  
  return (생략)
}

useEffect 안에 적으면 html을 보여주고 나서 반복문을 돌린다.

 

이런식으로 코드의 실행 시점을 조절할 수 있기 때문에 조금이라도 html렌더링이 빠른 사이트를 원하면 쓸데 없는 것들은 useEffect 안에 넣으면 좋다. (오래걸리는 반복연산이나, 타이머 등등)

 

 

 

처음엔 개념이 낯설어서 이해가 안됐지만 코딩애플 리액트 강의를 듣고 조금이나마 이해가 됐다.

전체 코드는 아래와 같다.

function App() {
  let [time, setTime] = useState(new Date())

 useEffect(()=>{
  const timer = setInterval(() => {
      setTime(new Date());
  }, 1000);
  return ()=>{
    clearInterval(timer)
  }
  }, []); 

  return (
    <div className='app'>
      <div className='header'>
        <h4>Time To Focus</h4>
      </div>

      <div className='allContent'>
        <div className='leftNav'>
          <div className='leftNavLink'>
            <Link to ="/">🌞 오늘 할 일</Link>
            <Link to="/tomorrowtodo">📆 내일 할 일</Link>
            <Link to="/someday">📅 추후</Link>
            <Link to="/rest">🙌 휴식</Link>
          </div>
          <div className='nowTime'>
            {time.toLocaleTimeString()}
          </div>
        </div>
      </div>
        <Routes>
          <Route path='/' element= {<Today />} />
          <Route path='/tomorrowtodo' element= {<Tomorrow />} />
          <Route path='/someday' element= {<Someday />} />
          <Route path='/rest' element= {<Rest />} />
        </Routes>
    </div>
  );
}

export default App;

 

 

 

다음 글에서는 투두리스트를 만들어 볼 예정이다😀

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함