React 데이터 다루기 (5)

깨진알·2023년 12월 29일

React

목록 보기
7/12

전역 데이터 다루기

1. Context


React Context

Context는 맥락을 의미하며, 상황에 대한 정보를 의미한다. 즉, 많은 컴포넌트에서 사용하는 데이터를 반복적인 Prop 전달(Prop Drilling) 없이 공유할 때 사용한다.


2. Context로 데이터 내려주기

import { createContext } from 'react';

const LocaleContext = createContext();

export default LocaleContext;

// App.js
return (
    <LocaleContext.Provider value="ko">
      <div>
        <div>
          <button onClick={handleNewestClick}>최신순</button>
          <button onClick={handleBestClick}>베스트순</button>
        </div>
        <ReviewForm
          onSubmit={createReview}
          onSubmitSuccess={handleCreateSuccess}
        />
        <ReviewList
          items={sortedItems}
          onDelete={handleDelete}
          onUpdate={updateReview}
          onUpdateSuccess={handleUpdateSuccess}
        />
        {hasNext && (
          <button disabled={isLoading} onClick={handleLoadMore}>
            더 보기
          </button>
        )}
        {loadingError?.message && <span>{loadingError.message}</span>}
      </div>
    </LocaleContext.Provider>
  );

// ReviewList.js
function ReviewListItem({ item, onDelete, onEdit }) {
  const locale = useContext(LocaleContext);

3. Context 값에 State 사용하기

function LocaleSelect({ value, onChange}) {

  const handleChange = (e) => onChange(e.target.value);

  return (
    <select value={value} onChange={handleChange}>
      <option value="ko">한국어</option>
      <option value="en">English</option>
    </select>
  );
}

export default LocaleSelect;

// App.js
const [locale, setLocale] = useState('ko');
...
  <LocaleContext.Provider value={locale}>
    <div>
    <LocaleSelect value={locale} onChange={setLocale} />

4. Context 코드 분리하기

import { createContext, useContext, useState } from 'react';

const LocaleContext = createContext();

export function LocaleProvider({ defaultValue = 'ko', children }) {
  const [locale, setLocale] = useState(defaultValue);

  return (
    <LocaleContext.Provider value={{ locale, setLocale }}>
      {children}
    </LocaleContext.Provider>
  );
}

export function useLocale() {
  const context = useContext(LocaleContext);

  if (!context) {
    throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
  }

  const { locale } = context;

  return locale;
}

export function useSetLocale() {
  const context = useContext(LocaleContext);

  if (!context) {
    throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
  }

  const { setLocale } = context;

  return setLocale;
}

5. 다국어 기능 완성하기

import { useLocale } from '../contexts/LocaleContext';

const dict = {
  ko: {
    'confirm button': '확인',
    'cancel button': '취소',
    'edit button': '수정',
    'delete button': '삭제',
  },
  en: {
    'confirm button': 'OK',
    'cancel button': 'Cancel',
    'edit button': 'Edit',
    'delete button': 'Delete',
  },
};

function useTranslate() {
  const locale = useLocale();
  const translate = (key) => dict[locale][key] || '';
  return translate;
}

export default useTranslate;

6. Context 정리

(1) 리액트 Context

Context는 한국어로 맥락이라는 뜻이다. 쉽게 말해서 어떤 상황에 대한 정보를 의미한다. '사용자가 한국어를 사용하는 상황', '사용자가 영어를 사용하는 상황' 같은 걸 여러 컴포넌트에 공유하고 싶을 때 사용한다. 컴포넌트의 단계가 많다면 여러 번 반복해서 Prop을 내려줘야 하는 문제점이 있는데 이를 프롭 드릴링(Prop Drilling)이라고 한다.

(2) Context 만들기

Context는 createContext라는 함수를 통해 만들 수 있다.

import { createContext } from 'react';

const LocaleContext = createContext();

기본값을 넣어줄 수도 있다.

import { createContext } from 'react';

const LocaleContext = createContext('ko');

(2) Context 적용하기

Context를 쓸 때는 반드시 값을 공유할 범위를 정하고 써야 한다. 이때 범위는 Context 객체에 있는 Provider라는 컴포넌트로 정해줄 수 있다. 이때 Providervalue prop으로 공유할 값을 내려주면 된다.

import { createContext } from 'react';

const LocaleContext = createContext('ko');

function App() {
  return (
    <div>
       ... 바깥의 컴포넌트에서는 LocaleContext 사용불가

       <LocaleContext.Provider value="en">
          ... Provider 안의 컴포넌트에서는 LocaleContext 사용가능
       </LocaleContext.Provider>
    </div>
  );
}

(3) Context 값 사용하기

useContext라는 Hook을 사용하면 값을 가져와 사용할 수 있다. 이때 아규먼트로 사용할 Context를 넘겨주면 된다.

import { createContext, useContext } from 'react';

const LocaleContext = createContext('ko');

function Board() {
  const locale = useContext(LocaleContext);
  return <div>언어: {locale}</div>;
}

function App() {
  return (
    <div>
       <LocaleContext.Provider value="en">
          <Board />
       </LocaleContext.Provider>
    </div>
  );
}

(4) State, Hook와 함께 활용하기

Provider 역할을 하는 컴포넌트를 하나 만들고, 여거시 State를 만들어서 value로 넘겨줄 수 있다. 그리고 아래의 useLocale 같이 useContext를 사용해서 값을 가져오는 커스텀 Hook을 만들 수 있다. 이렇게 하면 Context에서 사용하는 State 값은 반드시 우리가 만든 함수를 통해서만 쓸 수 있기 때문에 안전한 코드를 작성하는데 도움이 된다.

import { createContext, useContext, useState } from 'react';

const LocaleContext = createContext({});

export function LocaleProvider({ children }) {
  const [locale, setLocale] = useState();
  return (
    <LocaleContext.Provider value={{ locale, setLocale }}>
      {children}
    </LocaleContext.Provider>
  );
}

export function useLocale() {
  const context = useContext(LocaleContext);

  if (!context) {
    throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
  }

  const { locale } = context;
  return locale;
}

export function useSetLocale() {
  const context = useContext(LocaleContext);

  if (!context) {
    throw new Error('반드시 LocaleProvider 안에서 사용해야 합니다');
  }

  const { setLocale } = context;
  return setLocale;
}

7. 상태 관리의 짧은 역사

상태 관리(State Management)란, 화면에서 사용하는 데이터를 관리하는 것을 의미한다.

Flux : 데이터의 변경을 한 곳에서 하면서 흐름을 정리

Redux

React Query
SWR

Recoil : 전역적으로 쓸 수 있는 useState

profile
프론트엔드 지식으로 가득찰 때까지

0개의 댓글