[React 숙련] React Hooks(2)

Habin Lee·2023년 11월 9일
1

요약

  • React Hooks의 종류를 알고 적절하게 사용할 수 있다.
    : useContext

useContext

  • Context : 전역적으로 사용되는 어떠한 것을 표현할 때 사용

  • prop drilling 현상을 막기 위해 react context API가 나왔고
    -> useContext hook을 통해 쉽게 전역 데이터를 관리할 수 있게 됨

    출처 : https://www.copycat.dev/blog/react-context/

  • prop drilling에 대한 내용은 아래 게시글을 눌러 확인!
    prop drilling 설명

context API 필수 개념

  1. createContext : context 생성
  2. Consumer : context 변화 감지
  3. Provider : context 전달(to 하위 컴포넌트)

예시 코드

  • 아래의 코드를 보면 prop drilling이 일어난 것을 볼 수 있다.
    -> App > GrandFather > Father > Child
// App.jsx
import GrandFather from './components/GrandFather'

function App() {
  return (
    <GrandFather />
  )
}

export default App

// GrandFather.jsx
import React from 'react'
import Father from './Father';

function GrandFather() {
  const houseName = '스파르타';
  const pocketMoney = 10000;
  return (
    <Father houseName={houseName} pocketMoney={pocketMoney} />
  )
}

export default GrandFather

// Father.jsx
import React from 'react'
import Child from './Child'

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

export default Father

// Child.jsx
import React from 'react'

const style = {
  color: 'red',
  fontWeight: '900',
};
function Child({houseName, pocketMoney}) {
  return (
    <div>
      나는 이 집안의 막내예요! 
      <br />
      할아버지가 우리 집 이름은 <span style={style}>{houseName}</span>라고 하셨어요.
      <br />
      게다가 용돈도 <span style={style}>{pocketMoney}</span>원 만큼이나 주셨어요!
    </div>
  )
}

export default Child
  • 지금은 하나의 컴포넌트만 전달되는 것이지만 100개, 1000개 그 이상이 되면 오류가 났을 때 대처를 바로 하기가 쉽지 않다. -> 그래서 사용되는 것이 useContext다.

useContext를 사용한 예시 코드

  • 먼저 FamilyContext.js 파일을 만들고 createContext(null)을 FamilyContext로 선언하여 아래 데이터들을 넘겨주도록 한다.
// FamilyContext.js
import { createContext } from "react";

export const FamilyContext = createContext(null);

// GrandFather.jsx
import React from 'react'
import Father from './Father';
import { FamilyContext } from '../context/FamilyContext';

function GrandFather() {
  const houseName = '스파르타';
  const pocketMoney = 10000;
  /* Provider: 제공해주는자, 공급해주는자 라는 뜻으로,
     Father 컴포넌트 밑으로 이 컨텍스트를 제공해준다는 것이다.
     그리고 property로 value를 넘겨준다. */
  return (
    <FamilyContext.Provider value={{
      // key: value를 가져야하지만 key와 value가 같다면 value 생략 가능
      houseName,
      pocketMoney,
    }}>
      /* 원래 Father > Child 로 내려주는 props가 있었는데
         useContext를 사용하면 안내려줘도 됨 */
      <Father />
    </FamilyContext.Provider>
  )
}

export default GrandFather

// Father.jsx
import React from 'react'
import Child from './Child'

// 여기도 더이상 Child 컴포넌트에 내려줄 props를 가져오지 않아도 됨
function Father() {
  return (
    <Child />
  )
}

export default Father

// Child.jsx
import React, { useContext } from 'react'
import { FamilyContext } from '../context/FamilyContext';

const style = {
  color: 'red',
  fontWeight: '900',
};
// Child 컴포넌트에서도 props에 의존하는 것이 아니라 useContext에 의존한다.
function Child() {
  // context로부터 데이터를 받아온다. -> useContext 뒤에는 해당 컴포넌트가 들어온다.
  const data = useContext(FamilyContext);
  return (
    <div>
      나는 이 집안의 막내예요! 
      <br />
      // 이제 props를 이용하는게 아니라 context
      할아버지가 우리 집 이름은 <span style={style}>{data.houseName}</span>라고 하셨어요.
      <br />
      게다가 용돈도 <span style={style}>{data.pocketMoney}</span>원 만큼이나 주셨어요!
    </div>
  )
}

export default Child
  • 위 코드처럼 적으면 prop drilling이 일어나지 않고 데이터를 바로 가져다 쓸 수 있다.

useContext가 좋다고 남용하면 안되는 이유

  • 렌더링 문제 : useContext를 사용할 때, Provider(예시의 GrandFather 컴포넌트)에서 제공한 value가 달라진다면 useContext를 사용하고 있는 모든 컴포넌트(예시의 Father 컴포넌트 이하의 모든 컴포넌트)가 리렌더링 되어 엄청나게 비효율적이게 된다. 따라서 value 부분을 항상 신경써줘야 함.
    -> 그 대안이 이후에 배우게 될 메모이제이션이다.

느낀 점

리액트를 앞에서부터 조금씩 배우면서 느끼는거지만 '무조건 이게 좋다!' 하는 최고의 한 가지는 없고 그 대안을 위해 계속 무언가가 생기는 것이 참 신기했다. 그 당시에는 그게 가장 좋다고 생각했는데 단점이 나타나고, 그 단점을 메꾸기 위해 또 다른 것들이 생겨나고 그것들이 반복되어서 리액트라는 큰 덩어리가 된 것을 보니까 사람도 발전되는 모양새가 비슷하다는 것을 느꼈다. ㅎㅎ.. 코드를 보면서 이런 생각이 나는 걸 보니 기본 문과생은 어쩔 수 없나보다 🤣

0개의 댓글