한입크기 리액트 일기장11. 최적화 - useCallback

임하나·2023년 2월 12일
0

한입크기리액트

목록 보기
13/21

DiaryEditor React.memo로 감싸주어야하는데 DiaryEditor 기능을 한 함수들이 길기 때문에 이럴 경우에는 제일 하단에 export default 부분에 React.memo를 감싸주면된다.

export default React.memo(DiaryEditor);

렌더링 되는 부분을 확인해보자.

import React,{ useEffect, useState, useRef } from 'react';
useEffect(()=>{
  console.log('DiaryEditor 렌더');
})

렌더링이 2번발생한다.
App.js에서 처음 data의 빈 배열을 생성할때 렌더링이되고,
setData의 data값이 생성할때 렌더링이 되어 진다.
DiaryEditor는 onCreate로 부모요소의 값을 받고있다.
따라서 onCreate가 재생성 되지 않아야만 리렌더링이 되어지지 않는다.

앞에서 사용했던 useMemo를 사용하면안된다. 함수를 반환하는 것이 아니라, 값을 반환하는 것이기때문이다.
onCreate 아무기능없이 함수를 반환해야하기때문이다.

useCallback

메모이제이션된 콜백을 반환한다.

doSomething(a,b)를 반환한다.
두번째 값인 [a,b]의 값이 변화하지않으면 첫번째 인자로 반환한 콜백함수를 계속 재사용할 수 있도록 도와주는 리액트 훅이다.

import { useCallback } from 'react';
const onCreate = useCallback((author, content, emotion) => {
}, []);

삭제하기버튼을 누르면, 리렌더가 되지않는다.
그런데 일기를 생성하면, 기존에 있던 일기리스트들이 삭제되고.
최근에 쓴 일기만 저장이 된다.

useCallback 에 디펜런시어레이에 아무값도 넣어주지않아아서 그렇다. ([] 빈배열)
onCreate 의 함수가 마지막으로 실행한 것이 setData([newItem, ...data]); data 였기때문에 이런 현상이 발생하게 된 것이다.
data 초기값이 빈배열이기때문이다.

const onCreate = useCallback((author, content, emotion) => {
    const created_date = new Date().getTime();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      id : dataId.current
    }
    dataId.current += 1;
    setData([newItem, ...data]);
  }, [data]);

이런식으로 디펜던시 어레이에 [data]를 넣어주면되는데, 이럴 경우에도 data 계속 바뀔시 리렌더링됨으로. 일기리스트가 변화할때 계속 리렌더링이 되어 질 것이다.
이럴경우엔 함수형 업데이트를해주면된다.
setData에 함수로 전달해주면 된다.
상태변화함수에 함수를 전달하는 것을 함수형 업데이트라고 한다.
이럴떄 디펜던시어레이에 [data]값이 바워도 setData의 인자인 (data)를 최신의 값을 가져오기때문에 []값을 비울 수 있게된다.

const onCreate = useCallback((author, content, emotion) => {
  const created_date = new Date().getTime();
  const newItem = {
    author,
    content,
    emotion,
    created_date,
    id : dataId.current
  }
  dataId.current += 1;
  setData((data)=>[newItem, ...data]);
},[]);

이렇게 해주면 일기리스트를 생성해도, 이전 리스트를 다음에 생성되게되고, 일기를 삭제해도 리렌더링이 되지 않는다.

0개의 댓글