저는 평소에 useState useEffect 를 자주 사용합니다. 동작 원리를 모르고 사용하다 보니 나중에 오류가 나도 원인을 모르게 됩니다.그리고 올바르게 사용하고 있는 지도 모릅니다. react hooks의 종류에는 여러가지들이 있지만 이번 글에서는 제가 많이 사용했던 useState useEffect 두가지에 대해서 파먹어보도록 하겠습니다.
class 컴포넌트에는 라이프사이클 메서드가 존재합니다. 생명주기를 이용해서 컴포넌트가 생성되고 제거되는 과정의 특정시점에서 코드를 실행시킬 수 있는 것이죠. 하지만 함수형 컴포넌트 기반으로 React에서 해당 메서드가 필요할 경우 class를 이용한 코드를 작성해야 합니다. 이를 위해서 등장한 라이브러리가 React hooks 입니다. 19년 2월에 데이터 캐시가 개발되어 함수 컴포넌트가 어떤 값을 유지하고 이를 재사용할 수 있도록 캐시 가 만들어졌습니다. 그리고 이 캐시를 이용하고자 만든 여러개의 API가 React Hooks 입니다.
함수형 컴포넌트에서도 라이프사이클과 state 관리를 하게 해주는 라이브러리!
hook 은 여러번 호출이 가능합니다. 하지만 함수형 컴포넌트 내에서만 작동합니다. 복합 실행문{} 반복문에서는 사용할 수 없습니다.
const App = () => {
return {
<div>
<div>{const [value, setvalue] = useState()}</div>
</div>
}
}
비동기 함수는 콜백으로 사용할 수 없습니다.
const App = () => {
useEffect(async () => {
await Promise.resolve(1) // 땡!!
}, [])
return {
<div>
<div>Test</div>
</div>
}
}
제가 생각한 것보다 종류가 엄청 다양했습니다..--;
쨌든 이제 useState 와 useEffect에 대해 파고 들어봅시다.
state 는 react에서 사용자의 액션에 따라 화면에 다르게 출력(렌더)시키기 위해 사용되는 트리거역할의 변수입니다.
react는 setState 함수를 통해서 state의 값을 변경시킵니다.
setState는 state의 값을 즉시 변경하지 않고 현재 state와 setState의 인자를 비교하여 변경에 따른 정보를 리렌더링시키기는데 이때 state에 변경된 값이 부여됩니다.
import {useState} from 'react'
const App = () => {
const [count, setCount] = useState(0);
setCount(count + 1);
console.log(count); // console : 0;
}
예제 코드를 보겠습니다. count 라는 이름의 state 가 생성되었습니다. 이 후 바로 setCount가 실행되면서 count 의 값에 +1 를 해주었습니다.
import {useState} from 'react'
const App = () => {
const [count, setCount] = useState(0);
setCount(count++);
setCount(count++);
setCount(count++);
}
setCount가 세번 실행되었습니다. +1을 세번했으니 count의 값은 3이겠죠?
하지만 업데이트 시 count 의 값은 3이 아닌 1입니다.
변경될 count의 값을 업데이트 이전에 접근할 수는 없을까요? 있습니다!
import {useState} from 'react'
const App = () => {
const [count, setCount] = useState(0);
setCount((current) => current++);
setCount((current) => current++);
setCount((current) => current++);
}
이전 예제와 비슷해 보이지만 분명히 다른 부분이 있네요. setCount의 인자가 함수라는 점입니다. setState는 개체와 함수 두가지의 인자를 허용하는데요. 예제2는 개체이고 예시3은 함수를 인자로 전달하고 있습니다.
렌더링 이후에 코드를 실행시킵니다. deps 배열을 이용해 특정 상황에서만 의존적으로 코드를 실행시킬 수 있습니다. useEffect의 첫번째 인자는 함수를 실행시키고 두번째 인자는 의존값이 들어간 배열(deps)입니다. deps의 변화를 감지하고 업데이트될때 첫번째 인자의 함수를 실행시킵니다.
형태는 대충 이렇습니다.
useEffect(()=> {
deps의 값이 변경되었을때 해당코드 실행
},[deps])
import { useEffect } from 'react'
const App = () => {
const [count, setCount] = useState(0);
const onClick = () => {
setCount((current) => current++);
}
useEffect(()=> {
console.log('딩동')
},[])
}
deps 내 어떠한 값도 없는 빈배열 상태입니다. 리액트 데이터에 관여하는 어떠한 값도 사용하지 않겠다는 뜻입니다. 컴포넌트 내 의존성 검사를 생략하고 단 한번만 실행합니다.
componentDidMount
와 같습니다)⭐️ 빈 배열([])은 실제로 값이 사용되어야 할때 버그를 발생시키는 주된 원인이라고 합니다. 빈 배열을 이용해서 의존성 검사를 생략하는 것보다 의존성 검사를 필요로 하는 상황을 제거하는 방법들을 이용하는 것이 바람직하다고 합니다.(useReducer,useCallback 등)
import { useState, useEffect } from 'react'
const App = () => {
const [count, setCount] = useState(0);
const onClick = () => {
setCount((current) => current++);
}
useEffect(()=> {
console.log('딩동');
})
}
두번째 인자가 없는 경우 컴포넌트가 마운트가 완료되거나 업데이트가 완료될 때마다 매번 '딩동' 이 출력됩니다.
componentDidMount() || componentDidUpdate()
import { useState, useEffect } from 'react'
const App = () => {
const [count, setCount] = useState(0);
const onClick = () => {
setCount((current) => current++);
}
useEffect(()=> {
console.log(count);
return ()=> {console.log('clean up : 'count)} // <- clean up
})
}
이제 조금 이해하기 힘들 수 있습니다. useEffect 내에서 함수를 반환하고 있습니다.
componentDidMount()
하지만 컴포넌트가 제거되지 않았기 때문에 clean up 은 실행되지 않았습니다.componenetDidUpdate()
componentWillUnMount()
import { useState, useEffect } from 'react'
const App = () => {
const [count, setCount] = useState(0);
const onClick = () => {
setCount((current) => current++);
}
useEffect(()=> {
console.log('딩동')
},[count])
}
위 코드는 일반적인 useEffect 활용 예제라 할 수 있습니다. onClick 함수를 통해 count 의 값이 변경되면 console.log 가 실행되는 내용의 코드입니다.
componentDidMount()
)componentDidUpdate()
)useState를 통해 상태를 관리해왔지만 state가 어떻게 변경되고 적용되는 지 새로 알게되었습니다. 또한 변경이 적용되기 이전에 임시저장된 값에 접근할 수 있다는 내용도 새롭게 알게 되었습니다.그리고 useEffect를 통해 다양한 시점에서 코드를 실행하는 방법도 배우게 되었습니다. 제 눈높이에 맞추어 풀고 풀어서 설명하는 바람에 내용에 비해 글이 길어진 점이 있습니다. 글로 써내려가며 다시 한번 이해한 내용을 점검하고 react hook에 대해 잘 모르시는 분들께라도 도움이 되었으면 합니다.혹시 틀린 내용이 있다면 댓글로 지적해주시면 감사하겠습니다.
참고자료