Hook의 규칙
1. Hook은 무조건 최상위 레벨에서만 호출해야 한다.
- 반복문이나 조건문, 중첩된 함수들 안에서 Hook을 호출할 수 없다.
- Hook은 컴포넌트가 렌더링 될 때마다 매번 같은 순서로 호출되어야 한다.
⏩ useState(), useEffect()를 호출해서 컴포넌트의 state를 올바르게 관리할 수 있도록 한다.
📌 예제1. 잘못된 Hook 사용법
import { useEffect } from 'react';
function MyComponent(props) {
const [name, setName] = useState('yuns');
if(name !== '') {
useEffect(()=> {
...
});
}
...
}
⏩ 렌더링할 때마다 Hook이 같은 순서로 호출되지 않고, 조건문의 결과에 따라 호출되는 Hook이 달라진다.
2. 리액트 함수 컴포넌트에서만 Hook을 호출해야 한다. ( Class Component ❌ )
- 일반적인 자바스크립트 함수에서 Hook을 호출하면 안 된다. ✅ 리액트 함수 컴포넌트, 혹은 커스텀 훅에서만 호출 가능
eslint-plugin-react-hooks
- hook의 규칙을 따르도록 강제해주는 플러그인
- eslint : JavaScript 코드에서 발생하는 문제 코드를 식별하기 위한 정적 코드 분석 도구
- 참고 : https://www.npmjs.com/package/eslint-plugin-react-hooks
Custom Hook 만들기
- 목적 : 여러 컴포넌트에서 반복되는 로직을 Hook으로 만들어 재사용하기 위해
Custom Hook을 만들어야 하는 상황
📌 예제2-1. 리소스 1
import React, { useState, useEffect } from "react";
function UserStatus(props) {
const [ isOnline, setIsOnline ] = useState(null);
useEffect(()=>{
function handleStatusChange(status) {
setIsOnline(status.isOnline)
}
ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
return () => {
ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
};
});
if (isOnline === null) {
return '대기중...'
}
return isOnline ? '온라인' : '오프라인';
}
📌 예제2-2. 리소스 2
import React, { useState, useEffect } from "react";
function UserStatus(props) {
const [ isOnline, setIsOnline ] = useState(null);
useEffect(()=>{
function handleStatusChange(status) {
setIsOnline(status.isOnline)
}
ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
return () => {
ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
};
});
return (
<li style={{ color : isOnline ? 'green' : 'black'}}>
{props.user.name}
</li>
)
}
✅ 두 코드 중 중복되는 부분을 Custom Hook으로 추출한다.
Custom Hook 추출하기
중복되는 코드 존재하면, Custom Hook으로 만들어준다.
- Custom Hook : 이름이 'use-'로 시작하고, 내부에서 다른 Hook을 호출하는 하나의 자바스크립트 함수
📌 예제2-3. useUserStatus 커스텀 훅
import { useState, useEffect } from "react";
function useUserStatus(userId) {
const [ isOnline, setIsOnline ] = useState(null);
useEffect(()=>{
function handleStatusChange(status) {
setIsOnline(status.isOnline)
}
ServerAPI.subscribeUserStatus(props.user.id, handleStatusChange);
return () => {
ServerAPI.unsubscribeUserStatus(props.user.id, handleStatusChange);
};
});
return isOnline;
}
- 두 개의 컴포넌트에서 중복된 로직을 추출해서 가져옴
- 다른 컴포넌트(함수) 내부에서와 마찬가지로,
다른 Hook을 호출하는 것은 무조건 커스텀 훅의 최상위 레벨에서만 해야 한다.
- 커스텀 훅은, 다른 훅과 달리 단순한 함수에 지나지 않는다. ( 파라미터, 리턴 값을 사용자가 지정할 수 있다. )
- ➰ 다만, 앞에 'use-'를 붙여줘서 이것이 훅이라는 것을 명시해 준다.
Custom Hook 사용하기
- Custom Hook의 이름은 꼭 'use-'로 시작해야 한다.
- 여러 개의 컴포넌트에서 하나의 Custom Hook을 사용할 때, 컴포넌트 내부에 있는 모든 state와 effects는 전부 분리되어 있다. ⏩ state, effect에 대한 로직을 공유할 뿐, 값을 공유하지는 않는다.
✅ 각 Custom Hook 호출에 대해서 분리된 state를 얻게 된다. - 각 Custom Hook의 호출 또한 완전히 독립적이다.
Hook들 사이에서 데이터를 공유하는 방법
📌 예제3.
const userList = [
{ id: 1, name: 'Yuns'}
{ id: 2, name: 'Mike'}
{ id: 3, name: 'Steve'}
];
function ChatUserSelector(props) {
const [userId, setUserId] = useState(1);
const isUserOnline = useUserStatus(userId);
return (
<>
<Circle color={isUserOnline ? 'green' : 'red'} />
<select
value={userId}
onChange={event=> setUserId(Number(event.target.value))}
>
{userList.map(user=>(
<option key={user.id} value={user.id}>
{user.name}
</option>
))}
</select>
</>
)
}
useState()를 통해 데이터를 선언하고, 커스텀 훅 userUserStatus()가 이를 매개변수로 받고 있다.
'React' 카테고리의 다른 글
[React] Context 개념 및 특징 (0) | 2023.01.06 |
---|---|
[React] Composition VS. Inheritance - Containment, Specialization (0) | 2023.01.06 |
[React] React Hook의 종류 - useMemo(), useCallback(), useRef() (0) | 2022.12.29 |
[React] React Hook의 개념과 종류 - useState(), useEffect() (0) | 2022.12.29 |
[React] 리액트 Form의 특징과 종류 - 제어 컴포넌트 (0) | 2022.12.29 |
댓글