Hook
은 리액트 컴포넌트에서 상태와 이펙트를 도입하고 관리하는 효과적인 매커니즘.
Hook
이 등장하면서 더 이상 상태를 관리하기 위해서 Class를 사용할 필요가 없어졌다.
기존에는 Class형 컴포넌트에서만 상태를 관리할 수 있었다.
함수형 컴포넌트에서는 상태를 관리할 수 없었지만, Hook을 통해 상태 관리를 할 수 있게 되었고, 기존 클래스형 컴포넌트에서만 가능하던 여러 기능을 사용할 수 있게 되었다.
useState
는 state Hook이다.
state
를 편하게 관리할 수 있는 가장 기본적인 API.
useState
는 state
와 setState()
로 나뉘며 초기에 initialValue
를 받고, 해당 초기값은 처음 렌더링시에만 사용한다.
Hook은 쉽게 말하자면, 함수 컴포넌트에서 React state와 생명주기 기능(lifeCycle features)을 연동(hook into)할 수 있게 해주는 함수이다.
Hook을 통해 class 없이 리액트를 사용할 수 있다.
import React, { useState } from 'react'
function App() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onclict={() => setCount(count + 1)}>Click me!</button>
</div>
)
};
useEffect
는 effect Hook으로, 함수 컴포넌트에서 사이드 이펙트를 다룰 수 있게 해준다. 동기화
React Class의 componentDidMount
;처음 나타났을 때, componentDidUpdate
;특정 props가 바뀔 때, componentWillUnmount
;사라질 때와 같은 목적으로 제공되지만 하나의 API로 통합된 것.
리액트는 기본적으로 렌더링 이후에 effect를 실행한다.
effect함수는 컴포넌트 내에 있기 때문에 props와 state에 접근할 수 있다.
첫번째 렌더링과 이후 업데이트가 될 때 마다 effect가 수행된다.
정리
1. 화면이 처음 떴을 때 실행
- deps에 빈 배열[]
을 넣을 때.
- lifeCycle 중 componentDidmount처럼 실행.
2. 화면이 사라질 때 실행. (cleanup 함수)
- componentWillUnmount처럼 실행.
3. deps에 넣은 파라미터값이 업데이트 되었을 때 실행.
- componentDidUpdate처럼 실행.
useEffect
를 사용할 때, 첫번째 파라미터에는 함수, 두번째 파라미터에는 의존값이 들어있는 배열deps
을 넣는다.
만약에 deps
배열을 비워둔다면, 컴포넌트가 처음 나타날 때에만 useEffect
에 등록한 함수가 호출된다.
useEffect
에서는 함수를 반환할 수 있는데 이를 cleanup
함수라고 부른다.
cleanup
함수는 useEffect
에 대한 뒷정리를 해준다고 이해하자.
deps
가 비어있는 경우에는 컴포넌트가 사라질 때 cleanup
함수가 호출된다.
import React, { useEffect } from 'react';
function User({ user, onRemove, onToggle }) {
useEffect(() => {
console.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, []);
return (
<div>
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black'
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({ users, onRemove, onToggle }) {
return (
<div>
{users.map(user => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
export default UserList;
props
로 받은 값을 컴포넌트의 로컬 상태로 설정.deps
에 특정 값을 넣는다면 컴포넌트가 처음 마운트 될 때에도 호출이 되고, 지정한 값이 바뀔 때에도 호출이 된다.
deps
안에 특정 값이 있다면 언마운트시에도 호출이 되고, 값이 바뀌기 직전에도 호출이 된다.
import React, { useEffect } from 'react';
function User({ user, onRemove, onToggle }) {
useEffect(() => {
console.log('user 값이 설정됨');
console.log(user);
return () => {
console.log('user 가 바뀌기 전..');
console.log(user);
};
}, [user]);
return (
<div>
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black'
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({ users, onRemove, onToggle }) {
return (
<div>
{users.map(user => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
export default UserList;
useEffect
안에서 사용하는 state나 props가 있다면, useEffect
의 deps
에 넣어주어야 한다.
그렇지 않으면, useEffect
에 등록한 함수가 실행 될때 최신 props, state를 가리키지 않게 된다.
deps
파라미터를 생략한다면 컴포넌트가 리렌더링 될 때마다 호출이 된다.