Contents1. useEffect 2. useReducer 3. useMemo 4. useCallback 5. Custom Hook
React v16.8 부터 도입된 Hooks Api 를 통하여
클래스형 컴포넌트에서만 가능했던 state 관리, LifeCycle 등을
함수형 컴포넌트에서도 사용가능하게 되었습니다.
useEffect 를 사용하여 컴포넌트가 렌더링 될때 마다
특정 작업을 수행할 수 있습니다.
클래스형 컴포넌트와 비슷한 역할을 할 수 있습니다.
useEffect 는 기본적으로 모든 렌더링 이후에 실행되게 됩니다.
useEffect(() => {// to do something...})
하지만 useEffect 의 두 번째 파라미터에 빈 배열을 전달해 주면
컴포넌트가 마운트 될때만 실행되게 됩니다.
useEffect(() => {// to do something...}, [])
useEffect 의 두 번째 파라미터에 빈 배열 대신에
배열 안에 검사하고 싶은 값을 전달해 주면 컴포넌트가 마운트 될 때,
전달해 준 값이 변경될때 마다 실행되게 됩니다.
useEffect(() => {// to do something...}, [id])
컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 작업을 수행하고 싶으면
cleanup 함수를 반환(return) 해주어야 합니다.
useEffect(() => {
console.log('effect');
console.log(id);
return () => {
console.log('cleanup function');
console.log(id);
}
}, [id]);
위와 같이 두 번째 파라미터에 값을 전달하게 되면 id 값이 변경 될 때에
cleanup 함수와 effect 함수 모두 호출되게 됩니다.
또한 cleanup 함수에서 보여주는 id 값은 변경되기 이전의 값입니다.
두 번째 파라미터에 빈 배열을 전달하게 되면 cleanup 함수는
언마운트 될 때에만 호출되게 됩니다.
useReducer 를 사용하여 useState 보다 더 다양한
컴포넌트 상황에 따라 다양한 state 를 다른 값으로 업데이트 할 수 있습니다.
useReducer 는 다음과 같이 사용할 수 있습니다.
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 (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
useReducer 는 컴포넌트 업데이트 로직을 바깥으로 빼낼수 있다는 큰 장점이 있습니다.
useMemo 를 사용하여 컴포넌트 내부에서 발생하는 연산을 최적화 시킬 수 있습니다.
useMemo 를 사용하면 렌더링 과정에서 특정 값이 바뀌었을 때만
연산을 실행할 수 있습니다.
useMemo 는 다음과 같이 사용할 수 있습니다.
function computeExpensiveValue(a, b) {}
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
위와 같이 사용하게 되면 a 혹은 b 의 값이 변경 되었을 때에
computeExpensiveValue 함수가 실행되게 됩니다.
이 함수는 useMemo 와 비슷한 함수 입니다. 주로 렌더링 성능을
최적화 할 때에 사용되는 함수 입니다.
컴포넌트가 자주 렌더링 되거나 렌더링 할 컴포넌트의 갯수가 많아지면
useMemo 를 사용하여 렌더링 할 때마다 함수를 새로 메모리에 할당하지 않아도 됩니다.
useMemo 는 다음과 같이 사용할 수 있습니다.
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
}, [a, b]
);
위와 같이 두 번째 인자에 배열을 전달해 주면
memoizedCallback 함수는 a 또는 b 값이 변경 될때마다
함수가 생성되게 됩니다.
그리고 두 번째 인자에 빈 배열을 전달하면
처음 렌더링이 이루어 질때 함수가 생성됩니다.
Hook 을 개발자가 따로 작성하여 로직을 재사용 할 수 있습니다.
import { useReducer} from 'react';
function reducer(state, action) {
return {
...state,
[action.name]: action.value,
}
}
export default function useInputs(initialForm) {
const [state, dispatch] = useReducer(reducer, initialForm);
const onChange = (e) => {
dispatch(e.target);
};
return [state, onChange];
}
위와 같이 Hook 을 분리할 수 있습니다.