반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- #useRef #언제 쓰는데?
- DP #c++
- 백준 #적록색약
- raect typescript #react #typescript #styled-component
- RateLimit
- 노마드 코더 #타입스크립트 #typescript #class
- 버블링 #갭쳐링 #이벤트 #JS
- html entities
- 다익스트라 #파티 #백준
- JWT #토큰 #refreshToken #accessToken #Token #token #localStorage #sessionStorage
- React #리액트 이벤트 주기 #리액트 이벤트
- react fragment
- useState #Hooks
- interceptors
- 얕은 복사 #깊은 복사 #shallow copy #deep copy
- react #useCallback #react Hook
- 백준 #직각삼각형
- 빡킹독
- 이친수
- React #effect hook #useEffect
- 플로이드 #c++
- rate limit
- npm #not being able to find a file #npm install Error
- React #controlled component #비제어 컴포넌트 #제어 컴포넌트
- React #Hook rules #Hook 규칙
- donwstream #upstream #origin
- react
- 코드스테이츠 #알고리즘 #그리디
- axios
- React-Query
Archives
- Today
- Total
꿈꾸는 개발자
React Hook 규칙 정리 본문
Hook의 규칙(16.8 version에 추가된 기능)
https://www.npmjs.com/package/eslint-plugin-react-hooks
- 위 링크는 Hook 규칙을 강제하는 linter 플러그인
최상위(at the Top Level)에서만 Hook을 호출하라!
- 반복문, 조건문, 중첩함수 내에서 Hook 사용X + 최상위에서만 Hook 호출 => 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출됨 => useState/useEffect가 여러 번 호출되더라도, react에서 상태를 유지할 수 있게 됨!
오직 React 함수 내에서 Hook을 호출하라!(JS함수 내에 Hook 호출X)
- React 함수 component에서 Hook을 호출
- Custom Hook에서 Hook을 호출하라!
ESLint 플러그인
- Create React App에 기본적으로 내장돼 있음
npm install eslint-plugin-react-hooks --save-dev
// ESLint 설정 파일
{
"plugins": [
// ...
"react-hooks"
],
"rules": {
// ...
"react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
"react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
}
}
여러 Hook 사용:
function Form() {
// 1. name이라는 state 변수를 사용하세요.
const [name, setName] = useState('Mary');
// 2. Effect를 사용해 폼 데이터를 저장하세요.
useEffect(function persistForm() {
localStorage.setItem('formData', name);
});
// 3. surname이라는 state 변수를 사용하세요.
const [surname, setSurname] = useState('Poppins');
// 4. Effect를 사용해서 제목을 업데이트합니다.
useEffect(function updateTitle() {
document.title = name + ' ' + surname;
});
// ...
}
- 위와 같이 여러 Hook을 사용할 경우 리액트는 Hook이 호출되는 순서를 통해 특정 state가 어떤 useState 호출에 해당하는지 분별한다.
// ------------
// 첫 번째 렌더링
// ------------
useState('Mary') // 1. 'Mary'라는 name state 변수를 선언합니다.
useEffect(persistForm) // 2. 폼 데이터를 저장하기 위한 effect를 추가합니다.
useState('Poppins') // 3. 'Poppins'라는 surname state 변수를 선언합니다.
useEffect(updateTitle) // 4. 제목을 업데이트하기 위한 effect를 추가합니다.
// -------------
// 두 번째 렌더링
// -------------
useState('Mary') // 1. name state 변수를 읽습니다.(인자는 무시됩니다)
useEffect(persistForm) // 2. 폼 데이터를 저장하기 위한 effect가 대체됩니다.
useState('Poppins') // 3. surname state 변수를 읽습니다.(인자는 무시됩니다)
useEffect(updateTitle) // 4. 제목을 업데이트하기 위한 effect가 대체됩니다.
// ...
- Hook의 호출 순서가 렌더링 중 동일하면 => React는 지역적인 state를 각 Hook과 연동할 수 있다! BUT, 조건문 안에서 Hook을 사용할 경우 =>
// 🔴 조건문에 Hook을 사용함으로써 첫 번째 규칙을 깼습니다
if (name !== '') {
useEffect(function persistForm() {
localStorage.setItem('formData', name);
});
}
- 첫 번째 렌더링에서는 true일 것이다 => 하지만, 사용자가 다음 렌더링에서 form을 초기화 => 조건이 false로 변경된다 => (즉 form을 초기화할 경우 위 조건은 false이기 때문에 실행되지 않는다!) => 결국, Hook의 호출 순서가 달라지게 된다(렌더링에 마다)
useState('Mary') // 1. name state 변수를 읽습니다. (인자는 무시됩니다)
// useEffect(persistForm) // 🔴 Hook을 건너뛰었습니다!
useState('Poppins') // 🔴 2 (3이었던). surname state 변수를 읽는 데 실패했습니다.
useEffect(updateTitle) // 🔴 3 (4였던). 제목을 업데이트하기 위한 effect가 대체되는 데 실패했습니다
- React에서는 두 번째 Hook의 호출이 persistForm effect와 동일할 것으로 예상하고 시작 => 하지만 위에 설명한 이유로 생략된다 => 따라서, PASS된 Hook부터 하나씩 호출이 밀리면서 버그가 발생하게 된다!
- 이것이 바로 Component 최상위 즉 조건문 내부가 아닌, component scope level?에서 Hook을 사용하는 이유이다 => 만약 조건부로 effect을 실행하고 싶으면 Hook 내부에 작성해라!
useEffect(function persistForm() {
// 👍 더 이상 첫 번째 규칙을 어기지 않습니다
if (name !== '') {
localStorage.setItem('formData', name);
}
});
핵심 요약:
- Hook은 기본적으로 반복문, 조건문, 중첩함수 내에 사용X
- Hook은 함수 내에서만 호출
-이런 고민을 하기 귀찮다면, 리액트에서 제공하는 linter 플러그인을 install하자!
출처:
https://ko.reactjs.org/docs/hooks-rules.html