hooks 개요

hooks 개요

Hook 이 뭔가요?

Hook은 함수 컴포넌트에서 React state와 생명주기 기능을 연동(Hook Into) 할 수 있게 해주는 함수이다.

hooks 를 사용하면 class 컴포넌트가 아닌 함수형 컴포넌트로 생명주기 메서드와 동일한 기능을 사용할 수 있다.

버튼을 클릭하면 count가 1씩 증가형 rendering 하는 컴포넌트이다. 여기서 useState를 hooks 라고 하고 초기값을 입력하여 호출하면 값과 설정해주는 함수가 나온다. setCount와 같은 메서드는 클래스 컴포넌트에 this.setState와 같다고 할 수 있는데 setState 처럼 꼭 객체를 넣을 필요가 없고, 이전 state와 새로운 state를 합치지 않는다는 차이점이 있다.

1
2
3
4
5
6
7
8
9
10
11
12
function App() {
const [count, setCount] = React.useState(0);

return (
<>
<p> Conter is {count}</p>
<button onClick={() => setCount((prev) => prev + 1)}>Plus button</button>
</>
);
}

ReactDOM.render(<App />, document.getElementById("root"));

Effect Hook

컴포넌트 안에서 데이털르 가져오거나 구독하고, DOM을 직접 조작하는 작업을 종종 하게 된다. 이런 작업은 다른 컴포넌트에 영향을 줄 수도 있기 때문에 effect 또는 side effcect 라고 한다.

Effect Hook, 즉 useEffect는 side effects를 수행할 수 있게 해준다. 클래스 컴포넌트의 componentDidMount, componentDidUpdate, componentWillUnmount 와 같은 목적으로 제공된다.

다음 예는 동적으로 브라우저에 타이틀을 변경 시킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function App() {
const [count, setCount] = React.useState(0);

React.useEffect(() => {
document.title = `You Clicked ${count} times`;
}, [count]);

return (
<>
<p> Conter is {count}</p>
<button onClick={() => setCount((prev) => prev + 1)}>Plus button</button>
</>
);
}

ReactDOM.render(<App />, document.getElementById("root"));

마치 componentDidMountcomponentDidUpdate를 합쳐 놓은것과 같다.

만약 side effect를 일으키는 작업을 해제 시켜야 한다면 useEffect내에서 함수를 반환하면 된다. componentWillUnmount와 같다.

useEffect는 useState와 마찬가지로 여러 개를 사용할 수 있고, effect 해제와 같은 로직을 한곳에 작성할 수 있어서 관리하기 슆다.

Hook 사용 규칙

  • 최상위 에서만 Hook을 호출해야한다. 중첩된 함수에서 hook 실행 금지

  • React 함수 컴포넌트에서만 Hook 을 호출해야 한다. 일반 컴포넌트에서는 Hook 을 호출하면 안된다. 유일하게 허용하는 경우는 costomHook 에서다.

costom hook

커스텀 훅은 컴포넌트 트리에 새 컴포넌트를 추가하지 않고 상태 관련 로직을 재사용할 수 있게 해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { useState, useEffect } from "react";

function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);

function handleStatusChange(status) {
setIsOnline(status.isOnline);
}

useEffect(() => {
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});

return isOnline;
}

이것을 다른 컴포넌트에서 재사용할 수 있다.

1
2
3
4
5
6
7
8
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);

if (isOnline === null) {
return "Loading...";
}
return isOnline ? "Online" : "Offline";
}

다른 컴포넌트 :

1
2
3
4
5
6
7
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);

return (
<li style={{ color: isOnline ? "green" : "black" }}>{props.friend.name}</li>
);
}

Hook 은 state 자체가 아니다. Hook의 호출은 완전히 독립된 state를 가진다.

custom Hook 은 use 로 시작하고 안에서 Hook 을 호출한 것을 의미한다.

다른 내장 Hook

유용하다고 생각될 만한 내장 Hook 들이 몇몇 있다. 몇가지만 소개하면

useContext 는 컴포넌트를 중첩하지 않고도 React context를 구동할 수 있게 해준다.

1
2
3
4
5
function Example() {
const locale = useContext(LocaleContext);
const theme = useContext(ThemeContext);
// ...
}

useReducer 는 복잡한 컴포넌트들의 state를 reducer로 관리할 수 있게 해준다.

1
2
3
function Todos() {
const [todos, dispatch] = useReducer(todosReducer);
// ...