useRef훅 사용 예 const today: Date = useRef<Date>(new Date)
// 타입스크립트의 타입 추론 기능을 활용 타입 부분 생략 예 const today = useRef(new Date)
만일 값이 null일 수 있을 때는 값 타입에 합집합을 나타내는 | 구문을 사용한 다음 패턴을 사용합니다.
null 허용 훅 함수 사용 패턴 훅_함수<값_타입 | null>(값)
ex) useRef<Date | null>(new Date) << 이런식으로 사용하는것일 듯
매개변수 개수가 2개인 훅 함수들은 다음과 같은 코드 패턴을 공통으로 사용합니다. 여기서 의존성 목록은 콜백 함수에서 사용되는 변수나 함수의 값이 일정하지 않고 수시로 변할 수 있을때, 해당 변수나 함수를 아이템으로 갖는 배열을 의미합니다. 리액트 프레임워크는 의존성 목록에있는 아이템중 하나라도 변화가 있으면 콜백 함수를 새로 고침해 변한 값을 콜백 함수에 반영해 줍니다.
매개변수 2개인 훅 함수 코드 패턴 훅_함수<값의_타입>(콜백_함수, 의존성_목록)
다음은 매개변수 개수가 2개인 useEffect 훅을 사용하는 예입니다. 이코드는 콜백 함수를 가장 간단한 형태인 '()=>{}'로 구현했고 의존성 목록은 배열이어야 하므로 값이 변하는 변수나 함수가 없다는 의미로 빈 배열 []을 사용했습니다.
의존성이 빈 배열일 때 콜백 함수는 한 번만 실행 됩니다.
useEffect 훅 사용 예 useEffect(( ) => { }, [ ])
[ 4 ] setInterval API로 시계 만들기
자바스크립트는 setInterval 이라는 API를 기본으로 제공합니다. 이 API는 갱신 주기 때마다 콜백 함수를 계속 호출해 줍니다.
여기서 주의할점은 더이상 setInterval은 시스템 메모리 자원을 사용하므로 사용하지 않으려면 clearInterval 함수를 호출하여 메모리 누수가 생기지 않도록 해야합니다.
setInterval 콜백 함수를 멈추게 하는 clearInterval()함수 clearInterval(id
setInterval()을 사용해 시계를 만드는 코드
let today = new Date() const duration = 1000 const id = setInterval(() => { today = new Date() //현재 시간 갱신 }, duration)
이렇게 코드를 만들면 App라는 함수가 랜더링 될때마다 매번 setInterval이 호출이 발생한다는 문제가 있습니다.
setInterval이 함수는 처음 랜더링 될때 한 번만 호출되어야 하는데, 이때 useEffect를 사용하는게 좋아보입니다.
export default function App() { let today = new Date() const id = setInterval(() => { today = new Date() //현재시간 갱신 fourceUpdate() // 갱신된 시각이 웹화면에 반영 되도록 App을 다시 렌더링하는 함수가 필요합니다. }, 1000) }
fourceUpdate() 이런개념의 함수가 필요하다는 것이지 실제로 저런함수가 있는것이 아닙니다.
[ 5 ] useEffect 훅 사용하기
useEffect 훅을 사용하는 법을 배워봅시다
import { useEffect } from 'react'
위 코드를 추가해 주고 사용법은 밑에 글을 참고하면 됩니다.
useEffect(콜백_함수, 의존성목록) 콜백함수 = () => {}
useEffect는 의존성 목록에 잇는 조건 중 어느 하나라도 충족이 되면 그때마다 콜백함수를 다시 실행합니다.
컴포넌트가 실행될때 useEffect를 한번만 실행하게 하려면 의존성 목록을 []으로 빈값으로 만들면 됩니다. 그러면 콜백함수를 한번만 실행합니다.
한 번만 실행하는 useEffect 훅 사용법 useEffect(() => {}, [])
한 번만 호출하는 useEffect 훅 사용법 export default function App() { let time = new Date() useEffect(() =>{ const id = setInterval(() => { time = new Date() // 현재 시각 갱신 }, 1000) },[]) return <></> }
그런데 useEffect는 다음처럼 함수를 반환할 수 있습니다.
함수를 반환하는 useEffect useEffect( () => { // 컴포넌트가 생성될 때 실행 return () => {} // 컴포넌트가 소멸할 때 한번 실행 }, [])
다음은 useEffect훅을 사용하는 처음 코드입니다.
화면갱신이 버그가 있는 버전
import { useEffect, useState } from 'react'; import './App.css'; import Clock from './pages/Clock' function App() { let today = new Date(); useEffect(() => { console.log('useEffect called.') const duration = 1000 const id = setInterval(() => { today = new Date() console.log('today', today.toLocaleTimeString()) }, duration) return () => clearInterval(id) },[]) return ( <Clock today={today}></Clock> ); }
export default App;
위코드를 실행시키면 이렇게 에러가 나오고 화면이 실시간으로 갱신이 안된다.
Line 11:15: Assignments to the 'today' variable from inside React Hook useEffect will be lost after each render. To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property. Otherwise, you can move this variable directly inside useEffect react-hooks/exhaustive-deps
위 경고 에러는 무언가 리액트가 의도한 바대로 구현되지 않았음을 알려 줍니다.
setInterval 콜백 함수안에 time변수가 정상으로 갱신되고 있는데도 웹 브라우저 화면은 이를 반영하지 못하고 있습니다.
로그보면 초단위로 실행되고있다
리액트의 경고 메세지 대로 useRef훅을 사용해보겠습니다.
[ 6 ] useRef 훅 사용하기
today변숫값을 useRef 훅으로 설정해보겠습니다.
import { useEffect, useRef } from 'react'; import './App.css'; import Clock from './pages/Clock' function App() { let today = useRef(new Date()); useEffect(() => { console.log('useEffect called.') const duration = 1000 const id = setInterval(() => { today.current = new Date() console.log('today', today.current.toLocaleTimeString()) }, duration) return () => clearInterval(id) },[] ) return ( <Clock today={today.current}></Clock> ) }
export default App;
이렇게 코드를 수정하면 이제 경고와 에러는 없어지는데 실행화면은 여전히 갱신이 안된걸 볼 수 있다.
이제는 useRef와 유사하지만 컴포넌트를 다시 렌더링해 주는 useState훅을 사용해보겠습니다.
[ 7 ] useState 훅 사용하기
useState 임포트 하는법 import { useState } from 'react'
useState가 반환하는 세터는 현재 값이 변경되면 자동으로 해당 컴포넌트를 다시 렌더링하는 기능이 있습니다.