- [처음 만난 리액트] section 7. Hooks2024년 03월 27일 07시 21분 59초에 업로드 된 글입니다.작성자: 민발자728x90
1. Hooks의 개념과 useState, useEffect
1) Hook이란?
hook이란 함수 컴포넌트에 클래스 컴포넌트 기능(state, lifecycle)을 지원하기 위해 나온 것
리액트의 state와 생명주기 기능의 갈고리를 걸어 원하는 시점에 정해진 함수를 실행되도록 만든 것 → Hook
use---라고 명명해서 사용
2) useState
state를 사용하기 위한 hook
🔎 useState 사용법
버튼을 클릭하면 카운트를 증가하고 카운트를 보여주는 컴포넌트
버튼 클릭 시 카운트가 증가하지만 재렌더링이 일어나지 않아 증가되는 값을 보여줄 수 없음
버튼을 클릭하면 setCount 함수를 호출해 카운트가 증가하고 컴포넌트가 재렌더링되면서 화면에 새로운 카운트 값을 보여줌
🔎 useState 주의점
클래스 컴포넌트에서는 setState 함수 하나로 모든 state를 관리할 수 있지만
함수 컴포넌트에서는 변수마다 set함수가 필요
3) useEffect
side effect를 수행하기 위한 hook
🔎 Side Effect
리액트에서는 서버에서 데이터를 받아오거나 수동으로 DOM을 변경하는 등의 작업 의미
→ 다른 컴포넌트에 영향을 미칠 수 있고, 렌더링 중에는 작업이 완료될 수 없음
→ 렌더링이 끝난 이후에 실행되어야 함
→ 클래스 컴포넌트의 생명주기 함수와 동일한 기능을 제공
🔎 useEffect 사용법
의존성 배열 : 해당 이펙트가 의존하고 있는 배열, 배열의 값이 하나라도 변경되면 이펙트 함수 실행됨
일반적으로 처음 컴포넌트가 렌더링 된 이후와 업데이트로 인해 재렌더링 이후 실행
→ mount와 unmount에만 실행 : 빈 배열을 넣어주면 됨
→ 의존성 배열 생략 : 컴포넌트가 업데이트될 때마다 실행
2. useMemo, useCallback, useRef
1) useMemo
Memoized value를 리턴하는 Hook
memoization 개념을 이용해 다시 렌더링 될 때마다 연산량이 높은 작업을 반복하는 것을 피해 렌더링 속도를 높일 수 있음
🔎 Memoizationn
최적화를 위한 개념연산
연산량이 많이 드는 함수의 호출결과를 저장해 두었다가 같은 입력값으로 호출할 경우 이전에 저장해 놨던 호출 결과를 바로 반환
memoization 된 값을 Memoized value라고 함
🔎 useMemo 사용법
의존성 배열에 들어있는 변수가 변했을 경우에만 새로 함수 호출, 동일한 변수를 사용할 경우 기존 함수의 결괏값을 반환
🔎 useMemo 주의점
렌더링이 일어나는 동안 실행됨
렌더링이 일어나는 동안 작동하면 안되는 코드를 넣으면 안 됨
서버에서 데이터를 받아오거나 수동으로 DOM을 변경하는 작업 등은 렌더링이 실행되는 동안 작동하면 안 됨 → useMemo대신 useEffect 사용
2) useCallback
의존성 배열이 변경될 때만 함수를 새로 정의해 반환
useMemo와 유사하지만 값이 아닌 함수를 반환
🔎 useCallback 사용법
3) useRef
레퍼런스를 사용하기 위한 Hook
레퍼런스 객체를 반환
🔎 Reference
특정 컴포넌트에 접근할 수 있는 객체
🔎 useRef 사용법
초깃값으로 초기화된 레퍼런스를 반환
초깃값이 null인 경우 refObject.current 값이 nul인 객체 반환
refObject.current → 현재 참조하고 있는 Element
반환된 레퍼런스 객체는 컴포넌트가 마운트 해제 전까지 유지
클릭 시 마운트 된 inputElem에 접근하여 focus 함수 호출
🔎 useRef 주의점
내부의 데이터가 변경되었을 때 별도로 알리지 않음
→ 돔 노드의 변화를 알기 위해 callback ref 사용
3. Hook의 규칙과 Custom Hook 만들기
1) Hook의 규칙
최상위 레벨에서만 호출
반복문이나 조건문 또는 중첩된 함수들 안에서 호출하면 안 됨
컴포넌트가 렌더링 될 때마다 매번 같은 순서로 호출되어야 함
다수의 useState, useEffect에 호출해서 state를 올바르게 관리 가능
리액트 함수 컴포넌트에서만 호출
자바스크립트 함수에서 사용 불가, 리액트 함수 컴포넌트나 커스텀 Hook에서만 가능
잘못된 사용법
조건이 참일 경우에만 useEffect 호출, 조건문의 결과에 따라 Hook의 호출이 결정되므로 잘못된 사용법
2) Custom Hook 만들기
이름이 use로 시작하고 내부에서 다른 Hook을 호출하는 하나의 자바스크립트 함수
여러 컴포넌트에서 반복적으로 사용되는 로직을 Hook으로 만들어 재사용
여러 개의 컴포넌트에서 사용 시 컴포넌트 내부에 있는 모든 state와 effects는 전부 분리되어 있음
→ 각 custom Hook 호출에 대해서 분리된 state를 얻게 됨
각 custom Hook 호출 또한 완전히 독립적임
Hook 사이에서 데이터를 공유하기 위해선 파라미터로 공유
🔎 custom Hook을 만들어야 하는 상황
접속여부에 따라 텍스트로 반환하는 코드와 접속 상태를 색으로 보여주는 컴포넌트
useState, useEffect 부분이 동일 → custom Hook으로 추출가능
🔎 custom Hook으로 추출하기
중복되는 부분을 useUserStatus라는 커스텀 훅으로 추출
🔎 custom Hook 사용하기
useUserStatus
4. Hooks 사용해보기
📃 useCounter.jsx
import React, { useState } from 'react'; function useCounter(initialValue) { const [count, setCount] = useState(initialValue); const increaseCount = () => setCount((count) => count + 1); const decreaseCount = () => setCount((count) => Math.max(count -1 , 0)); return [count, increaseCount, decreaseCount]; } export default useCounter;
카운트 기능을 가진 custome hook을 만들어 어떤 함수 컴포넌트에서든지 카운트 기능을 사용 가능
📃 Accommodate.jsx
useCounter custome hook을 이용해 카운트 기능 사용
카운트가 최대 용량을 초과하면 경고 문구가 표시되고 더 이상 입장이 불가
useEffect 동작 방식 확인 위해 의존성 배열 없이, 있이 두 개 사용
import React, { useEffect, useState } from 'react'; import useCounter from './useCounter'; const MAX_CAPACITY = 10; function Accommodate(props) { const [isFull, setIsFull] = useState(false); const [count, increaseCount, decreaseCount] = useCounter(0); useEffect(() => { console.log("======================"); console.log("useEffect() is called."); console.log(`isFull: ${isFull}`); }); useEffect(() => { setIsFull(count >= MAX_CAPACITY); console.log(`Current count value: ${count}`); }, [count]); return ( <div style={{ padding: 16 }}> <p>{`총 ${count}명 수용했습니다.`}</p> <button onClick={increaseCount} disabled={isFull}> 입장 </button> <button onClick={decreaseCount}> 퇴장 </button> {isFull && <p style={{ color: "red" }}>정원이 가득찼습니다.</p>} </div> ); } export default Accommodate;
📃 index.js
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import reportWebVitals from './reportWebVitals'; import Accommodate from './chapter_07/Accommodate'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <Accommodate /> </React.StrictMode> ); reportWebVitals();
📊 결과
입장버튼을 누르면서 count 값이 변경
의존성 배열이 없는 useEffect는 컴포넌트가 업데이트되어 호출되고 의존성 배열이 있는 useEffect는 카운트 값이 변경되어 호출
최대 인원까지 추가 시 카운트 값이 더 이상 변하지 않기 때문에 의존성 배열이 있는 useEffect는 호출되지 않음
728x90'정리 > React' 카테고리의 다른 글
[처음 만난 리액트] section 6. State and Lifecycle (0) 2024.03.26 [처음 만난 리액트] section 5. Components and Props (0) 2024.03.25 [처음 만난 리액트] section 4. Rendering Elements (0) 2024.03.24 [처음 만난 리액트] section 3. JSX (0) 2024.03.23 [처음 만난 리액트] section 2. 리액트 시작하기 (0) 2024.03.23 다음글이 없습니다.이전글이 없습니다.댓글