// 그러면 useMemo, useReducer 등 고급 hook 들을 알려주세요!
React의 Hooks API는 useState와 useEffect 이외에도 많은 고급 Hooks를 제공합니다. 이 중 두 가지, useMemo와 useReducer에 대해 알아보겠습니다.
1. useMemo
useMemo는 메모이제이션(memoization)된 값을 반환합니다.
이는 비용이 많이 드는 연산의 결과값을 재활용하여 성능을 최적화하는 데 사용됩니다.
useMemo는 두 개의 인자를 받습니다. 첫 번째 인자는 값을 계산하는 함수이고,
두 번째 인자는 dependency array입니다. 이 배열에 명시된 값이 변경되었을 때만 첫 번째 인자의 함수가 호출되어 값이 재계산됩니다.
다음은 useMemo의 기본적인 사용 예제입니다:
import React, { useMemo } from 'react';
function MyComponent({ list }) {
const sortedList = useMemo(() => {
return list.sort((a, b) => a - b);
}, [list]);
return (
<div>
{sortedList.map((item, index) => (
<p key={index}>{item}</p>
))}
</div>
);
}
export default MyComponent;
위 코드에서는 list 배열이 변경될 때마다 새로 정렬되어, sortedList는 정렬된 배열을 메모이제이션된 값으로 갖게 됩니다.
2. useReducer
useReducer는 복잡한 상태 로직을 관리할 수 있게 해주는 Hook입니다.
이는 useState보다 더 유연한 API를 제공하며, 주로 상태 업데이트 로직이 복잡하거나 컴포넌트 간에 상태를 공유해야 하는 경우 사용됩니다.
useReducer는 두 개의 인자를 받습니다.
첫 번째 인자는 reducer 함수이고, 두 번째 인자는 초기 상태입니다. reducer 함수는 현재 상태와 액션을 인자로 받아 새로운 상태를 반환합니다.
다음은 useReducer의 기본적인 사용 예제입니다:
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</div>
);
}
export default Counter
위 코드에서는 버튼을 클릭할 때마다 'increment' 또는 'decrement' 액션을 dispatch하여 상태를 업데이트합니다.
이처럼 useMemo와 useReducer는 각각 성능 최적화와 복잡한 상태 관리를 돕는 고급 Hooks입니다.
실제 애플리케이션에서는 이러한 Hooks를 적절히 활용하여 효율적인 코드를 작성할 수 있습니다.
// 컴포넌트간에 상태를 공유해야 할때 useReducer를 사용하는 이유가 useReducer의 첫번째 인자로 함수를 따로 만들수 있어서 그런건가요?
그렇습니다, 그러나 이는 useReducer의 사용 사례 중 하나일 뿐입니다. useReducer Hook은 좀 더 복잡한 상태 업데이트 로직을 관리하기 쉽게 만드는 데 주로 사용됩니다.
useState Hook은 간단한 상태 업데이트를 위해 설계되었습니다. 반면에 useReducer는 액션에 따라 상태를 업데이트하는 방식으로 동작합니다. 이는 Redux와 같은 상태 관리 라이브러리에서 흔히 볼 수 있는 패턴입니다.
따라서, 컴포넌트 간에 상태를 공유해야 하거나 상태 업데이트 로직이 복잡한 경우 useReducer를 사용하는 것이 좋습니다. 특히 상태 업데이트가 이전 상태에 의존적이거나 여러 상태값을 포함하는 복잡한 상태 객체를 관리해야 하는 경우에 유용합니다.
또한 useReducer를 사용하면 상태 업데이트 로직을 컴포넌트 외부에 선언할 수 있으므로 테스트하기도 쉽고, 재사용 가능한 코드를 작성하는 데 도움이 될 수 있습니다.
이러한 이유로 useReducer는 복잡한 상태 업데이트 로직을 관리하거나 컴포넌트 간에 상태를 공유할 필요가 있는 경우에 사용되는 좋은 도구입니다.
// 고맙습니다. 그러면 useMemo 는 useEffect 와 유사해보이는데, 무엇이 다른 건가요?
useMemo와 useEffect는 비슷해 보일 수 있지만, 실제로는 각각 다른 목적으로 사용됩니다.
- useMemo: 이 Hook은 메모이제이션(memoization)에 사용됩니다. 즉, 비싼 계산 비용(computationally expensive)을 가지는 함수의 결과값을 저장해 두었다가, 의존성 배열의 값이 변경되지 않았다면 이전에 저장해둔 결과값을 재사용합니다. 이를 통해 불필요한 연산을 줄이고 성능을 최적화할 수 있습니다.
예를 들어, 아래 코드에서 computedValue는 value1과 value2가 변경되지 않는 한 다시 계산되지 않습니다.
const computedValue = useMemo(() => {
return expensiveComputation(value1, value2);
}, [value1, value2]);
- useEffect: 이 Hook은 사이드 이펙트(side effects)를 처리하는데 사용됩니다. 사이드 이펙트란 데이터를 가져오기, 구독 설정하기, 수동으로 React 컴포넌트의 DOM을 수정하는 것 등, 컴포넌트 내부에서 발생하는 일련의 동작을 말합니다. useEffect는 컴포넌트가 렌더링된 이후에 코드를 실행하게 하므로, 주로 비동기 작업에 사용됩니다.
예를 들어, 아래 코드에서는 컴포넌트가 렌더링될 때 API에서 데이터를 가져옵니다.
useEffect(() => {
fetchData().then((data) => setData(data));
}, []);
결국, useMemo와 useEffect는 각기 다른 목적을 가지고 있습니다.
useMemo는 연산 비용이 큰 함수의 결과값을 메모이징하고 재사용하기 위한 것이며, useEffect는 컴포넌트 렌더링 후에 실행할 코드를 정의하는 것입니다.
'react' 카테고리의 다른 글
[리액트 9] Context API (1) | 2024.01.04 |
---|---|
[리액트 8] useMemo, useReducer 추가 (0) | 2024.01.04 |
[리액트 6] useState, useEffect (0) | 2023.06.21 |
[리액트 5] 기본개념 - 이벤트, 폼 처리 (0) | 2023.06.21 |
[리액트 4] 기본개념 - 라이프사이클 (0) | 2023.06.21 |