반응형

1. useRef

특징 및 사용 목적

  • 값 저장: 컴포넌트가 다시 렌더링되어도 참조 값을 유지할 수 있습니다.
  • DOM 접근: 특정 DOM 요소에 직접 접근하거나 조작할 때 사용됩니다.
  • 렌더링 영향 없음: 값이 변경되어도 컴포넌트를 다시 렌더링하지 않습니다.

주요 사용 예시

  • DOM 요소의 포커스 제어, 크기/위치 확인
  • 이전 상태 값 저장
  • 타이머가 업데이트 될 때마다 불필요한 렌더링 방지
function Timer() {
  const timerRef = useRef(null);
  const [time, setTime] = useState(0);

  const startTimer = () => {
    if (!timerRef.current) {
      timerRef.current = setInterval(() => {
        setTime((prevTime) => prevTime + 1);
      }, 1000);
    }
  };

  const stopTimer = () => {
    clearInterval(timerRef.current);
    timerRef.current = null;
  };

  return (
    <div>
      <p>Time: {time}s</p>
      <button onClick={startTimer}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

2. useMemo

특징 및 사용 목적

  • 계산된 값의 캐싱: 복잡한 계산 결과를 캐싱하여 성능을 최적화합니다.
  • 종속성 배열: 지정된 종속성 값이 변경될 때만 다시 계산합니다.
  • 렌더링 성능 개선: 렌더링 과정에서 불필요한 계산을 방지합니다.

주요 사용 예시

  • 무거운 연산이나 데이터 변환 최적화
  • 컴포넌트에서 조건에 따라 변경되는 데이터 처리
  • 자식 컴포넌트에 전달할 복잡한 데이터 생성
function Parent() {
  const [count, setCount] = useState(0);

  const data = useMemo(() => {
    console.log('Generating data...');
    return { value: count };
  }, [count]); // `count`가 변경될 때만 데이터 재생성

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <Child data={data} />
    </div>
  );
}

function Child({ data }) {
  console.log('Child rendered');
  return <p>Child received: {data.value}</p>;
}

3. useCallback

특징 및 사용 목적

  • 함수 캐싱: 동일한 함수 객체를 재사용하여 불필요한 렌더링을 방지합니다.
  • 종속성 배열: 지정된 종속성이 변경될 때만 새로운 함수 객체를 생성합니다.
  • 자식 컴포넌트 최적화: React.memo와 함께 사용하여 불필요한 렌더링을 줄입니다.

주요 사용 예시

  • 부모 컴포넌트에서 자식 컴포넌트로 콜백을 전달할 때, 불필요한 재생성으로 인해 자식 컴포넌트가 다시 렌더링되지 않도록 하고 싶을 때.
function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount((prevCount) => prevCount + 1);
  }, []); // 동일한 함수 객체 유지

  return (
    <div>
      <p>Parent Count: {count}</p>
      <Child onClick={handleClick} />
    </div>
  );
}

const Child = React.memo(({ onClick }) => {
  console.log('Child rendered');
  return <button onClick={onClick}>Increment Parent Count</button>;
});

비교

Hook 사용 목적 렌더링 영향
useRef 값 저장, DOM 접근 X
useMemo 계산된 값 캐싱 O
useCallback 함수 캐싱, 자식 컴포넌트 최적화 O

useMemo, useCallback 의 차이는 미미하다.

https://www.linkedin.com/feed/update/urn:li:activity:7233818253674889217/

 

최효빈님의 LinkedIn 활동 보기

로그인 또는 회원 가입 후 더 확인해 보세요.

www.linkedin.com

 

useMemo(() => {{원하는함수}}, dependencies)
//useCallback 과 비슷해보이는 모습

 

훅으로 훅 만들기

리액트의 구현 방식 때문에 useReduceruseStateuseRefuseMemo 를 구현할 수 있다.

왜일까?

리액트 공식문서를 찾아보면, useRef, useMemo, useState 는 결국 fiber에 붙은 hook.memoizedState 를 반환하는 것. 또한, setState, dispatch역시 react-reconciler의 dispatch 함수를 어떤 형태로 반환하느냐의 차이다.

useReducer ⇒ useState

function useState<S>(initState: S | (() => S)) : [S, (action: SetStateAction>S>) => void] {
    const [state, dispatch] = useReducer(
        (state: S, action: SetStateAction<S>): S =>
            typeof action === 'function' ? (action as (prevState: S) => S)(state) : action,
        typeof initState === 'function' ? (initState as () => S)() : initState
    );

    return [state, dispatch];
} 

useRef ⇒ useMemo

function useMemo<T>(factory: () => T, deps: React.DependencyList): T {
    const ref = useRef<{ value : T; deps: React.DependencyList | undefined }>){
        value: undefined as T,
        deps : undefined,
    });

    if(!ref.current_deps || !shallowEqual(deps, ref.current.deps)) {
        ref.current.value = factory();
        ref.current.deps = deps;
    }

    return ref.current.value;
}

useMemo ⇒ useCallback

function useCallback<T extends (...args: any[]) => any>(
    callback: T,
    deps: React.DependencyList
): T {
    return useMemo(() => callback, deps);
}
반응형

'Web > React' 카테고리의 다른 글

React 번들링  (1) 2024.12.01
React의 특징  (2) 2024.11.17

+ Recent posts