[REACT] ⭐useCallback - 컴포넌트 최적화 3

짱효·2023년 11월 13일
0

REACT

목록 보기
16/29
post-thumbnail

컴포넌트 최적화

  • 어떤 컴포넌트가 리랜더링 되는지 보여주는 기능
  • console.log는 너무 번거러움

컴포넌트 최적화 이유

  • 1이 삭제되면 2가 리렌더링 될 이유가 없다.

  • 컴포넌트가 길어 이름에 묶어주기 힘들다하면 export에서 묶어주기

//⭐ 맨마지막에 묶어주기
export default React.memo(DiaryEditor);


-onceate 함수를 다시 리랜더링 안하게

useMemo vs useCallback

useMemo : 값 반환
useCallback: 함수 반환

-⭐useMemo을 사용하면 안됨, 값을 반환하는것이여서 안됨.

  • 우리는 함수 그대로를 반환해야함
  // ⭐useMemo는 값을 반환하는것이여서 안됨.
  const onCreate = (author, content, emotion) => {
    const created_date = new Date().getTime();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      //어떤 돔도 가르키지 않고 0이라는 값을 가지고있다.
      id: dataId.current,
    };
    dataId.current += 1;
    setData([newItem, ...data]);
  };

-⭐useMemo는 값을 반환하는것이여서 안됨.

useCallback

  • 의존성 배열이 비어있어야 리랜더링 가능성이 ⬇️

  • 메모이져션된 콜백함수를 반환한다.

함수형 업데이트

  • 상태변환 함수에 함수를 넣어준다.
  const onCreate = useCallback((author, content, emotion) => {
    const created_date = new Date().getTime();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      //어떤 돔도 가르키지 않고 0이라는 값을 가지고있다.
      id: dataId.current,
    };
    dataId.current += 1;
    //❤️함수형 업데이트: 상태변환 함수에 함수를 넣어준다.
    // 항상 최신의 값
    setData([newItem, ...data]);
  },[data]);
  • useCallback을 쓰니까 data 값이 다 사라짐

  • [] : dependency array에 아무값도 없어서 이거 떄문..

  • 컴포넌트는 마운트 순간에만 랜더링

  • 데이터 스테이스값이 빈배열

  • 함수 재생성

해결방법(setDate에 함수로 전달)

  • 함수형 업데이트
  • 화살표함수로 전달.
  • ⭐최신의 state를 인자를 통해 업데이트됨. (의존성 배열을 지워도 됨.)
  const onCreate = useCallback((author, content, emotion) => {
    const created_date = new Date().getTime();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      //어떤 돔도 가르키지 않고 0이라는 값을 가지고있다.
      id: dataId.current,
    };
    dataId.current += 1;
    //❤️함수형 업데이트: 상태변환 함수에 함수를 넣어준다.
    // 항상 최신의 값
    setData((data) => [newItem, ...data]);
  }, []);
import { useState, useRef, useEffect, useMemo, useCallback } from "react";
import "./App.css";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";
// import OptimizeTest from "./OptimizeTest";

function App() {
  const [data, setData] = useState([]);
  // 변수처럼 사용
  const dataId = useRef(0);

  //데이터 가져오는 함수
  const getData = async () => {
    const res = await fetch(
      "https://jsonplaceholder.typicode.com/comments"
    ).then((res) => res.json());

    const initData = res.slice(0, 20).map((it) => {
      return {
        author: it.email,
        content: it.body,
        //Math.floor 정수로 바꿔줌, 0~4여서 +1 해줌
        emotion: Math.floor(Math.random() * 5) + 1,
        created_date: new Date().getTime(),
        // id 만들기. useRef 의 .current
        id: dataId.current++,
      };
    });
    setData(initData);
  };

  //라이프 사이클, 컴포넌트가 생성되면
  useEffect(() => {
    // 데이터를 가져온다.
    getData();
  }, []);

  //새로운 데이터를 추기하는 함수
  // ⭐useMemo: 값
  // ⭐useCallback: 함수
  const onCreate = useCallback((author, content, emotion) => {
    const created_date = new Date().getTime();
    const newItem = {
      author,
      content,
      emotion,
      created_date,
      //어떤 돔도 가르키지 않고 0이라는 값을 가지고있다.
      id: dataId.current,
    };
    dataId.current += 1;
    //⭐함수형 업데이트: 상태변환 함수에 함수를 넣어준다.
    // ⭐항상 최신의 값
    setData((data) => [newItem, ...data]);
    //⭐의존성 배열 언제나 빈값으로 유지
  },[]);

  const onRemove = (targetId) => {
    //filter로 제외해서 새로운 배열
    const newDiaryList = data.filter((it) => it.id !== targetId);
    //setData에 새로운 배열 추가
    setData(newDiaryList);
  };
  // item의 수정기능을 App에서 !수정되는 아이디와 수정되는 내용
  const onEdit = (targetId, newContent) => {
    setData(
      //  it아이디가 맞으면 content에 새로운 내용을 넣어준다(삼항연산자)
      data.map((it) =>
        it.id === targetId ? { ...it, content: newContent } : it
      )
    );
  };

  //일기 감정 분석 함수
  //⭐useMemo
  // 이건 함수가 아니라 값이다.
  const getDiaryAnalysis = useMemo(() => {
    const goodCount = data.filter((it) => it.emotion >= 3).length;
    const badCount = data.length - goodCount;
    const goodRatio = (goodCount / data.length) * 100;
    //값을 객체로 리턴
    return { goodCount, badCount, goodRatio };
    //⭐data 길이가 변하면 업데이트 됨.
  }, [data.length]);

  //함수를 연산자로 변수로 나누기
  // ⭐useMemo는 함수로 말고 값으로 사용해야한다.getDiaryAnalysis() (x) =>getDiaryAnalysis
  const { goodCount, badCount, goodRatio } = getDiaryAnalysis;

  return (
    <div className="App">
      <DiaryEditor onCreate={onCreate} />
      <div>전체 일기 : {data.length}</div>
      <div>기분 좋은 일기 개수: {goodCount}</div>
      <div>기분 나쁜 일기 개수: {badCount}</div>
      <div>기분 좋은 일기 비율: {goodRatio}</div>
      <DiaryList onEdit={onEdit} onRemove={onRemove} diaryList={data} />{" "}
      {/* 더미 리스트 프롭스로 전달 */}
    </div>
  );
}

export default App;
profile
✨🌏확장해 나가는 프론트엔드 개발자입니다✏️

0개의 댓글