useContext, 최적화

박재민·2024년 1월 30일
0

TIL

목록 보기
26/49

- useContext 필요성

기존 props를 사용하여 데이터를 전달 할 땐 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달했는데, prop drilling 현상으로 인해서 props가 어떤 컴포넌트로 부터 왔는지 파악이 어려워진다. 또한 오류가 발생 시 추적이 힘들어져서 대처도 늦게 되는데, 이걸 해결 해주는 API 가 useContext 다.

useContext 미사용 시

// App.jsx

import "./App.css";
import GrandFather from "./components/GrandFather";
export function App() {
  return <GrandFather />;
}

export default App;
// GrandFather

import React from "react";
import Father from "./Father";

function GrandFather() {
  const grandFatherName = "마동석";
  const pocketMoney = 50000;

  return <Father grandFatherName={grandFatherName} pocketMoney={pocketMoney} />;
}

export default GrandFather;
// Father

import React from "react";
import Child from "./Child";

function Father({ grandFatherName, pocketMoney }) {
  return <Child grandFatherName={grandFatherName} pocketMoney={pocketMoney} />;
}

export default Father;
// Child

import React from "react";

function Child({ grandFatherName, pocketMoney }) {
  const stressedWord = {
    color: "#9370DB",
    fontWeight: "900",
  };
  return (
    <div>
      우리 할아버지의 성함은 <span style={stressedWord}>{houseName}</span> 이다.
      <br />
      할아버지께서 용돈을 <span style={stressedWord}>{pocketMoney}</span> 원이나
      주셨다.
    </div>
  );
}
export default Child;
- 결과 : 우리 할아버지의 성함은 마동석 이다. 할아버지께서 용돈을 50000원이나 주셨다.

useContext 사용 시

// FmailyContext.js

import { createContext } from "react";

export const FamilyContext = createContext(null);
// GrandFather

import React from "react";
import Father from "./Father";
import { FamilyContext } from "../context/FamilyContext";

function GrandFather() {
  const grandFatherName = "마동석";
  const pocketMoney = 50000;

  return (
    <FamilyContext.Provider value={{ grandFatherName, pocketMoney }}>
      <Father />
    </FamilyContext.Provider>
  );
}

export default GrandFather;
// Father

import React from "react";
import Child from "./Child";

function Father() {
  return <Child />;
}

export default Father;
// Child
import React, { useContext } from "react";
import { FamilyContext } from "../context/FamilyContext";

function Child({ grandFatherName, pocketMoney }) {
  const stressedWord = {
    color: "red",
    fontWeight: "900",
  };

  const data = useContext(FamilyContext);
  console.log("data", data);

  return (
   <div>
      우리 할아버지의 성함은 <span style={stressedWord}>{data.grandFatherName}</span> 이다.
      <br />
      할아버지께서 용돈을 <span style={stressedWord}>{data.pocketMoney}</span> 원이나
      주셨다.
    </div>
  );
}

export default Child;
- 결과 : 우리 할아버지의 성함은 마동석 이다. 할아버지께서 용돈을 50000원이나 주셨다.
위처럼 useContext 를 사용 시 중간 컴포넌트에서 복잡한 과정을 거치지 않고 최종적으로 전달하고 싶은 컴포넌트에 데이터를 전달 할 수 있다.

- 주의사항

useContext를 사용할 때, Provider에서 제공한 value가 달라진다면 useContext를 사용하고 있는 모든 컴포넌트가 리렌더링 된다. 따라서 value 부분을 항상 신경써줘야 한다.

- 최적화

리렌더링이 발생하는 3가지

1. 컴포넌트에서 state가 바뀌었을 때
2. 컴포넌트가 내려받은 props가 변경되었을 때
3. 부모 컴포넌트가 리-렌더링 된 경우 자식 컴포넌트 모두
리렌더링이 자주 발생하는건 그만큼 비용이 발생한다는 의미이기 때문에 최소화 해야한다. 이 때 하는 작업을 "최적화(Optimization)" 라고 한다.

대표적으로 최적화 하는 방법

1. memo(React.memo) : 컴포넌트를 캐싱
2. useCallback : 함수를 캐싱
3. useMemo : 값을 캐싱

- memo(React.memo)

리렌더링 발생 조건 중 3번째인 부모 컴포넌트가 리렌더링 될 때 자식 컴포넌트 모두 리렌더링 되는 상황을 해결해준다.

- memo(React.memo)

useCallback 은 인자로 들어오는 함수 자체를 기억한다.

- memo(React.memo)

맨 처음 해당 값을 반환할 때 그 값을 특별한 곳(메모리)에 저장해서 필요할 때 마다 함수를 호출해서 계산하는것이 아닌 이미 저장한 값 을 꺼내와서 쓸 수 있게 해준다.

그러나 useMemo를 남발하게 되면 별도의 메모리 확보를 너무나 많이 하게 되기 때문에 오히려 성능이 악화될 수 있기때문에 필요시에만 사용해야 한다.

0개의 댓글