(React)(ts) UseContext 훅

최 재성·2023년 6월 21일

React

목록 보기
9/15

컨텍스트란?

리액트 컨텍스트(React Context)는 리액트 애플리케이션에서 전역적인 데이터를 효율적으로 공유하기 위한 메커니즘입니다. 컨텍스트를 사용하면 컴포넌트 트리를 깊이 내려가지 않고도 데이터를 전달할 수 있으며, 중간 컴포넌트에서 프로퍼티로 데이터를 전달하는 번거로움을 줄일 수 있습니다.

  1. 상태와 데이터를 전역적으로 공유하고 전파하기 위해 사용됩니다.
  2. 중앙 집중화된 데이터 관리와 상태 업데이트를 가능하게 합니다.
    • 여러 컴포넌트에서 동일한 데이터를 공유하고 동기화할 수 있게 합니다
  3. 컴포넌트 간의 결합도를 감소시키고 의존성을 낮춥니다.
  4. 외부 라이브러리나 플러그인과의 통합을 용이하게 합니다.
  5. 다국어 지원, 테마 관리, 사용자 인증 등의 공통 데이터 관리에 유용합니다.

Context는 상태 관리와 데이터 공유를 간편하게 하며, 컴포넌트 간의 결합도를 낮추어 유연성을 높여줍니다. 그러나 남용하거나 너무 많은 컴포넌트에 영향을 주는 경우에는 주의해야 합니다. 적절하게 사용하면 컴포넌트 간의 데이터 전달과 관리를 효과적으로 할 수 있습니다.


모든 컨텍스트 제공자는 가장 최상위 컴포넌트로 동작해야 하는것이 원칙입니다.

1.createContext 함수 호출

  • createContext 함수 호출 패턴
import React,{createContext} from 'react'

type ContextType = {
  //공유할 데이터 속성
}
const defaultContextValue: ContextType = {
  //공유할 데이터 속성 초깃값
}
const SomeContext = createContext<ContextType>(defaultContextValue)

createContex 함수로 생성된 컨텍스트 객체는 아래 컴포넌트를 제공합니다.

  1. <Context.Provider>: 컨텍스트 값을 제공하는 컴포넌트입니다. 하위 컴포넌트에서 이 값을 접근하고 사용할 수 있습니다. <Context.Provider>는 value prop을 통해 값을 전달합니다.

  2. <Context.Consumer>: 컨텍스트 값을 소비하는 컴포넌트입니다. <Context.Consumer> 컴포넌트 내부에 함수를 정의하고, 이 함수의 매개변수로 컨텍스트 값이 전달됩니다. 이 함수를 통해 컨텍스트 값을 활용할 수 있습니다.

  3. useContext(): 훅(Hook)을 사용하여 컨텍스트 값을 가져올 수 있는 함수입니다. 함수의 인자로 컨텍스트 객체를 전달하면, 해당 컨텍스트의 값을 반환합니다.
    함수 컴포넌트 사용시, useContext 사용. 사용법이 단순함.


interface ProviderProps<T>{
  value: T;
  children?: ReactNode;
}

Provider 컴포넌트는 value,children 속성이 있는 ProviderProps 속성을 제공 합니다. 여기서 타입변수 T는 createContext<T>와 같아야 합니다.

context를 이용한 예제. 반응형 컨텍스트 만들기.

아래 코드는 ResponsiveProvider라는 컴포넌트를 사용하여 ReponsiveContext를 생성하고 값을 제공하는 예제입니다.

  1. ResponsiveProvider 컴포넌트는 useWindowResize(커스텀훅) 훅을 사용하여 창의 크기를 가져와서 중단점(breakpoint) 값을 설정합니다.
  2. 해당 값을 ReponsiveContext.Provider의 value prop으로 전달하여 하위 컴포넌트에서 사용할 수 있도록 합니다.

하위 컴포넌트에서는 useResponsive 훅을 사용하여 breakpoint 값을 가져올 수 있고 이를 이용하여 이미지의 크기, 레이아웃 등을 조절하거나 다른 스타일을 적용할 수 있습니다.
useResponsive 훅을 사용하면 중단점에 따라 컴포넌트의 동작이나 표시 방식을 조정할 수 있습니다.

즉, 상위 컴포넌트에서 제공한 중단점 값을 하위 컴포넌트에서 가져와서 그에 따라 렌더링을 조정하는 것이 가능합니다.

import { FC, PropsWithChildren, createContext, useContext } from 'react'
import { useWindowResize } from '../hooks/useWindowResize'

//컨텍스트 패턴
type ContextType = {
  breakpoint: string
}
const defaultContextValue: ContextType = {
  breakpoint: ''
}
//createContext 로 공유할 속성, 기본값을 저장.
export const ReponsiveContext = createContext<ContextType>(defaultContextValue)

//창의 크기가 변하면 그 값을 가져와 크기에 맞는 중단점 설정. Provider value 에 값 지정. (공유할 값)

type ResponsiveProviderPorps = {}
export const ResponsiveProvider: FC<PropsWithChildren<ResponsiveProviderPorps>> = ({
  children,
  ...props
}) => {
  //창의 크기를 가져올 커스텀 훅.
  const [width] = useWindowResize()
  const breakpoint =
    width < 640
      ? 'sm'
      : width < 768
      ? 'md'
      : width < 1024
      ? 'lg'
      : width < 1280
      ? 'xl'
      : '2xl'

  const value = {
    breakpoint
  }

  return <ReponsiveContext.Provider value={value} children={children} />
}

export const useResponsive = () => {
  const { breakpoint } = useContext(ReponsiveContext)
  return breakpoint
}

아래 코드와 같이 useResponsive 훅을 호출하여 breakpoint 값을 가져온 후, 해당 값을 JSX 내부에서 사용합니다. 예제에서는 <SubTitle> 컴포넌트를 통해 breakpoint 값을 표시하고 있습니다.

이렇게 하면 ResponsiveContextTest 컴포넌트는 ResponsiveProvider 컴포넌트에서 제공되는 중단점 값을 사용할 수 있습니다. 따라서 해당 컴포넌트는 중단점에 따라 조건부로 표시되는 내용이나 스타일을 적용할 수 있게 됩니다.

import { useResponsive } from '../contexts'
import { Title, SubTitle } from '../components'

export default function ResponsiveContextTest() {
  
  const breakpoint = useResponsive()
  
  return (
    <section className="mt-4">
      <Title>ResponsiveContextTest</Title>
      <div>
        <SubTitle>breakpoint : {breakpoint}</SubTitle>
      </div>
    </section>
  )

0개의 댓글