🟥 훅 (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에 렌더링된 직후마다 실행됩니다.

클래스형 컴포넌트에서 사용하는 componentDidMountcomponentDidUpdate를 합친 형태로 보아도 무방합니다.

 

  • 마운트 될 때만 실행하고 싶을 때

함수의 두 번째 파라미터로 빈 배열을 넣어주면 최초 마운트 될 때만 한 번 실행 됩니다.

useEffect( () => {
  console.log("마운트될 때만 실행됩니다.");
}, []);

 

  • 특정 값이 업데이트될 때만 실행하고 싶을 때

함수의 두 번째 파라미터로 검사하고 싶은 state값을 넣어주면 됩니다. 

아래 내용은 name의 상태가 변경될 때 마다 log를 찍는 로직입니다.

useEffect( () => {
  console.log("name");
}, [name]);

 

  • 뒷정리하기

컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떤 작업을 필요로 하는 경우, useEffect함수 내에서 후처리를 위한 함수를 반환해 주어야 합니다.

useEffect( () => {
  console.log("effect");
  return () => {
    console.log('cleanup');
  }
}, [] ); // 오직 언마운트시에만 후처리 함수를 호출하고 싶다면 두번째 파라미터에 빈배열을 넘긴다.

 

 

 

🔸 useReducer

useReduceruseState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트하고 싶을 때 사용하는 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);

첫 번째 파라미터로는 메모이제이션 하고자하는 함수를 전달하고, 두 번째 파라미터로는 상태 변경 모니터링이 필요한 stateprops를 전달합니다. 

 

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가 변경되지 않는 한, 이전 결과를 그대로 사용하기 때문에 중복된 계산을 피할 수 있습니다. 

+ Recent posts