🟥 훅 (Hooks)
리액트 v16.8 부터 도입된 개념으로
원래 함수형 컴포넌트에서는 state관리가 불가능했으나,
함수형 컴포넌트에서도 상태관리를 할 수 있도록 도입된 기술입니다.
useState, useEffect, useReducer, useMemo, useCallback
🔸 useState
상태를 관리하기 위한 가장 기본적인 훅 입니다.
...
const [count, setCount] = useState(0); //useState의 인자로는 초기값을 넘겨줍니다.
onClick = () => {
setCount(count+1);
}
return (
<>
<div>{count}</div>
<button onClick={onClick}</button>
</>
)
...
useState의 인자로는 상태관리를 위한 초기값을 넘겨줍니다.
그러면 배열이 반환되는데, 첫번째 인자는 현재의 상태(state)를 나타내고, 두번째 인자는(setCount)는 상태를 업데이트할 때 실행되는 함수명입니다.
🔸 useEffect
컴포넌트가 실제 DOM에 렌더링된 직후마다 실행됩니다.
클래스형 컴포넌트에서 사용하는 componentDidMount와 componentDidUpdate를 합친 형태로 보아도 무방합니다.
- 마운트 될 때만 실행하고 싶을 때
함수의 두 번째 파라미터로 빈 배열을 넣어주면 최초 마운트 될 때만 한 번 실행 됩니다.
useEffect( () => {
console.log("마운트될 때만 실행됩니다.");
}, []);
- 특정 값이 업데이트될 때만 실행하고 싶을 때
함수의 두 번째 파라미터로 검사하고 싶은 state값을 넣어주면 됩니다.
아래 내용은 name의 상태가 변경될 때 마다 log를 찍는 로직입니다.
useEffect( () => {
console.log("name");
}, [name]);
- 뒷정리하기
컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떤 작업을 필요로 하는 경우, useEffect함수 내에서 후처리를 위한 함수를 반환해 주어야 합니다.
useEffect( () => {
console.log("effect");
return () => {
console.log('cleanup');
}
}, [] ); // 오직 언마운트시에만 후처리 함수를 호출하고 싶다면 두번째 파라미터에 빈배열을 넘긴다.
🔸 useReducer
useReducer는 useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트하고 싶을 때 사용하는 Hook입니다.
카운터 구현하기
import { useReducer } from 'react';
function reducer(state, action) {
swtich (action.type) {
case 'INCREMENT' :
return { value : state.value + 1 }
case 'DECREMENT' :
return { value : state.value - 1 }
default :
// 아무것도 해당되지 않으면 기존상태 반환
return state;
}
}
const Counter = () => {
const [state, dispatch] = useReducer(reducer, { value: 0});
return (
<div>
<p>
현재 카운터 값은 <b>{state.value}</b>입니다.
</p>
<button onClick={ () => dispatch({type : 'INCREMENT'})}>+1</button>
<button onClick={ () => dispatch({type : 'DECREMENT'})}>-1</button>
);
};
export default Counter;
useReducer에 첫 번째 파라미터로는 리듀서 함수를 넣고, 두 번째 파라미터에는 해당 리듀서의 기본값을 넣어줍니다.
이 훅을 사용하면 state 값과 dispatch 함수를 받아오는데, 여기서 state는 현재 카리키는 상태이고, dispatch는 액션을 발생시키는 함수입니다.
useReducer 사용시 가장 큰 장점은 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼낼 수 있다는 것입니다.
🔸 useCallback
성능 최적화를 위해 사용되는 훅 중 하나입니다.
useCallback을 이용하면 함수를 메모이제이션해 함수 인스턴스의 재사용이 가능합니다.
함수컴포넌트 안에서 함수를 만들어 사용하면, 컴포넌트가 렌더링될 때 마다 새로 만들어진 함수 인스턴스를 사용하게 되며, 이는 성능에 악영향을 줄 수 있습니다.
따라서 최적화가 필요한 상황에 사용합니다.
const memoizedCallback = useCallback(callbackFunction, dependencyArray);
첫 번째 파라미터로는 메모이제이션 하고자하는 함수를 전달하고, 두 번째 파라미터로는 상태 변경 모니터링이 필요한 state나 props를 전달합니다.
import React, { useState, useCallback } from 'react';
function Counter() {
const [ count, setCount ] = useState(0);
const handleClick = useCallback( () => {
setCount(count+1);
}, [count]);
return (
<div>
<p>Counter: {count}</p>
<button onClick={handleClick} />
</div>
);
}
count가 변경되지 않는 한, 같은 함수 인스턴스가 재사용되어 불필요한 리렌더링을 방지할 수 있습니다.
🔸 useMemo
useCallback과 같이 성능 최적화를 위해 사용되는 훅 중 하나입니다.
useCallback이 컴포넌트의 함수 인스턴스를 재 사용하기 위해 사용한다면, useMemo는 연산 비용이 높은 계산 결과를 메모이제이션하기 위해 사용합니다.
const memoizedValue = useMemo(() => computeValue, dependecyArray);
useMemo는 값을 캐시하므로, 이전 계산 결과를 재사용해 성능을 향상시킬 수 있습니다.
import React, { useState, useMemo } from 'react';
function ExpensiveComponent({data}) {
const expensiveResult = useMemo(() => {
// data 배열 요소들을 모두 합산하는 연산 (고비용)
return data.reduce((sum, num) => sum+num, 0);
}, [data] );
return <div>Expensive Result: {expensiveResult}</div>;
}
위의 예시에서 data 배열이 변경될 때 마다 expensiveResult를 다시 계산합니다.
그렇지 않으면, 캐시된 결과를 사용해 비용을 아끼고 성능을 향상시킵니다.
data가 변경되지 않는 한, 이전 결과를 그대로 사용하기 때문에 중복된 계산을 피할 수 있습니다.
'리액트' 카테고리의 다른 글
[리액트] - 컴포넌트의 라이프사이클, 라이프사이클 메서드 (0) | 2023.08.30 |
---|---|
[리액트] - State와 Props (0) | 2023.08.29 |
[리액트] - 개념, 컴포넌트, JSX (0) | 2023.08.29 |