[React] useCallback

박소정·2023년 12월 16일
0

React

목록 보기
21/26
post-thumbnail

useCallback란? 🧐

컴포넌트가 리렌더될 때 내부에 작성된 함수를 다시 생성하지 않도록 메모이제이션하는 리액트 훅이다.

사용법 👏

첫 번째 인수로는 메모이제이션하려는 콜백 함수를 전달하고, 두 번째 인수로는 의존성 배열을 전달한다.

const memoizedFunc = useCallback(func, deps)
  • 적용

    다음은 현재 진행중인 '할 일 관리' 프로젝트의 일부이다. (전체 코드는 여기)
    import "./App.css";
    import Header from "./component/Header.js";
    import TodoEditor from "./component/TodoEditor.js";
    import TodoList from "./component/TodoList.js";
    import { useReducer, useRef } from "react";

    const mockTodo = [
      {
        id: 0,
        isDone: false,
        content: "React 공부하기",
        createdDate: new Date().getTime(),
      },
      {
        id: 1,
        isDone: true,
        content: "컴활 공부하기",
        createdDate: new Date().getTime(),
      },
    ];

    function reducer(state, action) {
      switch (action.type) {
        case "CREATE": {
          return [action.newItem, ...state];
        }
        case "UPDATE": {
          return state.map((it) =>
            it.id === action.targetId
              ? {
                  ...it,
                  isDone: !it.isDone,
                }
              : it
          );
        }
        case "DELETE": {
          return state.filter((it) => it.id !== action.targetId);
        }
        default:
          return state;
      }
    }

    function App() {
      const [todo, dispatch] = useReducer(reducer, mockTodo);
      const idRef = useRef(3);

      const onCreate = (content) => {
        dispatch({
          type: "CREATE",
          newItem: {
            id: idRef.current,
            content,
            isDone: false,
            createdDate: new Date().getTime(),
          },
        });
        idRef.current += 1;
      };

      const onUpdate = (targetId) => {
        dispatch({
          type: "UPDATE",
          targetId,
        });
      };

      const onDelete = (targetId) => {
        dispatch({
          type: "DELETE",
          targetId,
        });
      };

      return (
        <div className="App">
          <Header />
          <TodoEditor onCreate={onCreate} />
          <TodoList todo={todo} onUpdate={onUpdate} onDelete={onDelete} />
        </div>
      );
    }
    export default App;

함수 onUpdate와 onDelete를 useCallback으로 메모이제이션을 하여 함수들을 다시 생성하지 않도록 만든다.

  const onUpdate = useCallback((targetId) => {
    dispatch({
      type: "UPDATE",
      targetId,
    });
  }, []);

  const onDelete = useCallback((targetId) => {
    dispatch({
      type: "DELETE",
      targetId,
    });
  }, []);

최적화할 때 유의할 점

  • 최적화는 항상 마지막에 한다.

    기능을 추가할 때마다 최적화를 진행하지 않고 마지막에 한꺼번에 하는 이유는 최적화 이후에는 만든 기능을 수정하거나 확장하기 어렵다.
  • 모든 것을 최적화할 필요는 없다.

    향후 서비스 확장이나 기능 수정을 어렵게 만들고, 전체적인 웹 서비스 성능 개선에도 큰 도움이 되지 않는다.
  • 컴포넌트 구조를 잘 설계했는지 다시 한번 돌아본다.

    컴포넌트를 기능이나 역할 단위로 잘 분리했는지 먼저 확인한 다음 최적화를 한다.

0개의 댓글