생활코딩! React 리액트 프로그래밍

egoing - Context API - stackblitz ver

lshjju 2025. 9. 6. 09:53

Context API


https://lshjju.tistory.com/147

 

React.js - Context API - 리액트 콘텍스트 에이피아이

React.js - Context API - 리액트 콘텍스트 에이피아이 1. Context API는 왜 필요한가요? (Props Drilling 문제)React에서 컴포넌트 간에 데이터를 전달할 때 기본적으로 Props를 사용합니다. 부모 컴포넌트에서 자

lshjju.tistory.com



Final build


https://stackblitz.com/edit/vitejs-vite-od3slcbk?file=src%2FApp.jsx

 

egoing - Context API - StackBlitz

Next generation frontend tooling. It's fast!

stackblitz.com



New project building

https://lshjju.tistory.com/104

 

StackBlitz web editor - 스택블리츠 웹 에디터

스택블리츠로 새 프로젝트 생성하기 https://stackblitz.com/ 로그인 방법 선택 대쉬보드에서 new project + 버튼 - 탭 모달 - frontend 탭 - 탭react javascript - 탭 바이트 리액트가 생성됩니다.프로젝트 생성 완

lshjju.tistory.com



간단한 박스를 만듭니다.


/* null */

 

index.css

 

이 파일은 비웁니다.


.root,
.root div {
  border: 10px solid gray;
  margin: 10px;
  padding: 10px;
}

 

App.css

 

간단한 스타일을 준비 합니다.


export default function App() {
  return (
    <div className="root">
      <h1>Hello World</h1>
      <Sub1 />
    </div>
  );
}

 

App.js

 

펑션앱을 위 코드로 세팅 합니다.

디브에 클래스네임 루트 추가합니다.

서브1 태그 추가 합니다.

// `App` 함수형 컴포넌트를 정의하고 `export default`를 사용하여 이 파일을 대표하는 컴포넌트로 내보냅니다.
// 이 컴포넌트가 애플리케이션의 시작점 역할을 합니다.
export default function App() {
  // `App` 컴포넌트는 JSX를 반환합니다.
  return (
    // `className`이 'root'인 최상위 `div` 요소를 렌더링합니다.
    <div className="root">
      {/* 'Hello World'라는 텍스트를 포함하는 h1 태그를 렌더링합니다. */}
      <h1>Hello World</h1>
      {/* `Sub1` 컴포넌트를 렌더링합니다. 이로 인해 `Sub1` 내의 `Sub2`, `Sub3`도 연쇄적으로 렌더링됩니다. */}
      <Sub1 />
    </div>
  );
}

function Sub1() {
  return (
    <div>
      <h1>Sub1</h1>
      <Sub2 />
    </div>
  );
}

function Sub2() {
  return (
    <div>
      <h1>Sub2</h1>
      <Sub3 />
    </div>
  );
}

function Sub3() {
  return (
    <div>
      <h1>Sub3</h1>
    </div>
  );
}

 

펑션앱 위에 펑션서브1 2 3 을 만듭니다.

코드페이스트 잘못 하면 무한루프 걸려서 브라우저 탭이 셧다운 될것입니다.

셧다운 되면 다시 리로드 하자마자 자식 태그를 빨리 지우면 괜찮아 집니다.

조심 합니다.

// `Sub1` 함수형 컴포넌트를 정의합니다.
function Sub1() {
  // `Sub1` 컴포넌트는 JSX를 반환합니다.
  return (
    // 최상위 `div` 요소를 렌더링합니다.
    <div>
      {/* 'Sub1'이라는 텍스트를 포함하는 h1 태그를 렌더링합니다. */}
      <h1>Sub1</h1>
      {/* `Sub2` 컴포넌트를 렌더링합니다. */}
      <Sub2 />
    </div>
  );
}

// `Sub2` 함수형 컴포넌트를 정의합니다.
function Sub2() {
  // `Sub2` 컴포넌트는 JSX를 반환합니다.
  return (
    // 최상위 `div` 요소를 렌더링합니다.
    <div>
      {/* 'Sub2'라는 텍스트를 포함하는 h1 태그를 렌더링합니다. */}
      <h1>Sub2</h1>
      {/* `Sub3` 컴포넌트를 렌더링합니다. */}
      <Sub3 />
    </div>
  );
}

// `Sub3` 함수형 컴포넌트를 정의합니다.
function Sub3() {
  // `Sub3` 컴포넌트는 JSX를 반환합니다.
  return (
    // 최상위 `div` 요소를 렌더링합니다.
    <div>
      {/* 'Sub3'라는 텍스트를 포함하는 h1 태그를 렌더링합니다. */}
      <h1>Sub3</h1>
    </div>
  );
}

test

박스를 체크 합니다.


Completion

import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';

function Sub1() {
  return (
    <div>
      <h1>Sub1</h1>
      <Sub2 />
    </div>
  );
}

function Sub2() {
  return (
    <div>
      <h1>Sub2</h1>
      <Sub3 />
    </div>
  );
}

function Sub3() {
  return (
    <div>
      <h1>Sub3</h1>
    </div>
  );
}

export default function App() {
  return (
    <div className="root">
      <h1>Hello World</h1>
      <Sub1 />
    </div>
  );
}


박스를 모두 벌겋게 바꿉니다.


import { createContext, useContext } from "react";

 

모든 회색 박스를 벌겋게 바꿀겁니다.

그러기 위해 크리에잇콘텍스트, 유즈콘텍스트 임포트 합니다.

// React의 `createContext`와 `useContext`를 임포트합니다.
// `createContext`는 컨텍스트 객체를 생성하며, `useContext`는 이 컨텍스트를 함수 컴포넌트에서 구독할 수 있도록 합니다.
import { createContext, useContext } from "react";

const themeDefault = { border: "10px solid green" };
const themeContext = createContext(themeDefault);

 

임포트 아래에 테마디폴트 스타일을 추가합니다.

테마디폴트를 사용하는 테마콘텍스트를 초기화 합니다.

이러면 테마디폴트가 이것의 디폴트가 됩니다.

스타일 원본를 만들었다 생각하면 편할것 같습니다.

// 기본 테마 객체를 정의합니다. 이 객체는 모든 컴포넌트에 공통으로 적용될 스타일 속성을 포함합니다.
const themeDefault = { border: "10px solid green" };
// `createContext`를 사용하여 `themeContext` 컨텍스트 객체를 생성합니다.
// `themeDefault`는 이 컨텍스트의 기본값으로 사용됩니다.
const themeContext = createContext(themeDefault);

export default function App() {
  const theme = useContext(themeContext);
  console.log("theme", theme);
  return (
    <div className="root" style={theme}>
      <h1>Hello World</h1>
      <Sub1 />
    </div>
  );
}

 

유즈콘텍스트를 콤포넌트 내부에서 로딩 합니다.

테마콘텍스트를 사용하는 테마를 초기화 합니다.

 

테마 로그 찍어 봅니다.

테마디폴트가 테마의 디폴트인 것을 체크 합니다.

즉, 스타일 기본값은 여전히 살아 있습니다.

  console.log("theme", theme);

 

펑션앱 디브에 테마 스타일을 적용합니다.

테마의 디폴트는 테마디폴트이므로 펑션앱 보더가 초록색으로 변경됩니다.

// `App` 함수형 컴포넌트를 정의하고 `export default`를 사용하여 이 파일을 대표하는 컴포넌트로 내보냅니다.
// 이 컴포넌트가 애플리케이션의 시작점 역할을 합니다.
export default function App() {
  // `useContext` 훅을 사용하여 `themeContext`로부터 현재 테마 값을 가져옵니다.
  const theme = useContext(themeContext);
  // 콘솔에 현재 `theme` 값을 출력합니다. 이는 개발 과정에서 테마 값이 올바르게 전달되는지 확인할 때 유용합니다.
  console.log("theme", theme);
  // `App` 컴포넌트는 JSX를 반환하며, 가져온 `theme` 스타일을 최상위 div에 적용합니다.
  return (
    <div className="root" style={theme}>
      <h1>Hello World</h1>
      <Sub1 />
    </div>
  );
}

function Sub1() {
  const theme = useContext(themeContext);
  return (
    <div style={theme}>
      <h1>Sub1</h1>
      <Sub2 />
    </div>
  );
}

function Sub2() {
  const theme = useContext(themeContext);
  return (
    <div style={theme}>
      <h1>Sub2</h1>
      <Sub3 />
    </div>
  );
}

function Sub3() {
  const theme = useContext(themeContext);
  return (
    <div style={theme}>
      <h1>Sub3</h1>
    </div>
  );
}

 

펑션서브123에도 테마를 적용해 봅니다.

프롭스를 사용하지 않았지만 데이터가 글로벌하게 사용되고 있습니다.

이것이 콘텍스트에이피아이 기능입니다.

// `Sub1` 함수형 컴포넌트를 정의합니다.
function Sub1() {
  // `useContext` 훅을 사용하여 `themeContext`로부터 현재 테마 값을 가져옵니다.
  // 이렇게 가져온 테마는 이 컴포넌트와 그 자식 컴포넌트에서 사용할 수 있습니다.
  const theme = useContext(themeContext);
  // `Sub1` 컴포넌트는 JSX를 반환하며, 가져온 `theme` 스타일을 div에 적용합니다.
  return (
    <div style={theme}>
      <h1>Sub1</h1>
      <Sub2 />
    </div>
  );
}

const themeDefault = { border: "10px solid red" };

 

테마디폴트 스타일 칼라를 변경 하고 테마디폴트가 모두 적용되는지 체크합니다.


test


Completion

import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { createContext, useContext } from 'react';

const themeDefault = { border: '10px solid red' };
const themeContext = createContext(themeDefault);

function Sub1() {
  const theme = useContext(themeContext);
  return (
    <div style={theme}>
      <h1>Sub1</h1>
      <Sub2 />
    </div>
  );
}

function Sub2() {
  const theme = useContext(themeContext);
  return (
    <div style={theme}>
      <h1>Sub2</h1>
      <Sub3 />
    </div>
  );
}

function Sub3() {
  const theme = useContext(themeContext);
  return (
    <div style={theme}>
      <h1>Sub3</h1>
    </div>
  );
}

export default function App() {
  const theme = useContext(themeContext);
  console.log('theme', theme);
  return (
    <div className="root" style={theme}>
      <h1>Hello World</h1>
      <Sub1 />
    </div>
  );
}


박스를 벌겋게 퍼렇게 싱싱하게 바꿉니다.


function Sub1() {
  const theme = useContext(themeContext);
  return (
    <themeContext.Provider value={{ border: "10px solid green" }}>
      <div style={theme}>
        <h1>Sub1</h1>
        <Sub2 />
      </div>
    </themeContext.Provider>
  );
}

 

서브23을 그린으로 변경합니다.

그러기 위해 부모인 서브1 코드를 변경합니다.

서브1을 프로바이더로 래핑해서 테마콘텍스트를 공급합니다.

프로바이더는 밸류가 반드시 필요 합니다.

밸류는 그린을 적용합니다.

 

자식이 유즈콘텍스트를 사용하는 경우 부모의 모든 자식은 부모가 공급하는 스타일을 받습니다.

그러므로 서브23은 그린으로 변경됩니다.

 

즉, 자식컴포넌트에 유즈 콘텍스트를 사용하면 부모컴포넌트 첫번째 프로바이더 밸류가 모든 자식들에게 일괄 적용됩니다.

별것 아닌것처럼 보이지만 자식이 만약 100개라면 생각이 달라질 것입니다.

// Sub1이라는 이름의 함수형 컴포넌트입니다.
function Sub1() {
  // 'useContext' 훅을 사용하여 'themeContext'에서 현재 테마 값을 가져옵니다.
  // 이 컴포넌트는 부모인 App 컴포넌트의 Provider로부터 'blue' 테마를 받게 될 거예요.
  const theme = useContext(themeContext);
  return (
    // 'themeContext.Provider'를 사용하여 Sub1 컴포넌트와 그 하위 컴포넌트들에게 새로운 테마 값을 제공합니다.
    // 여기서는 테마가 'green'으로 변경되어 Sub2와 Sub3는 'green' 테마를 받게 됩니다.
    <themeContext.Provider value={{ border: '10px solid green' }}>
      {/* 가져온 테마 값을 div의 스타일에 적용합니다. */}
      <div style={theme}>
        <h1>Sub1</h1>
        {/* Sub2 컴포넌트를 렌더링합니다. Sub2는 여기서 제공하는 'green' 테마를 따를 거예요. */}
        <Sub2 />
      </div>
    </themeContext.Provider>
  );
}

export default function App() {
  const theme = useContext(themeContext);
  console.log("theme", theme);
  return (
    <themeContext.Provider value={{ border: "10px solid blue" }}>
      <div className="root" style={theme}>
        <h1>Hello World</h1>
        <Sub1 />
      </div>
    </themeContext.Provider>
  );
}

 

서브1을 블루로 변경합니다.

위와 마찬가지로 서브1을 변경하기 위해 서브1의 부모인 펑션앱 수정합니다.

이것이 콘텍스트에이파이이가 데이터 글로벌 콘트롤, 상속 콘트롤 하는 방법입니다.

// 애플리케이션의 가장 메인이 되는 'App' 컴포넌트입니다.
export default function App() {
  // 'useContext' 훅을 사용하여 'themeContext'에서 현재 테마 값을 가져옵니다.
  // 이 App 컴포넌트 자신은 어떤 Provider로도 감싸져 있지 않으므로,
  // 위에서 정의한 'themeDefault'(red 테마)를 사용하게 됩니다.
  const theme = useContext(themeContext);
  // 현재 'App' 컴포넌트가 어떤 테마 값을 받고 있는지 콘솔에 출력합니다.
  // 위에서 설명한 것처럼 'red' 테마가 찍힐 거예요.
  console.log('theme', theme);
  return (
    // 'themeContext.Provider'를 사용하여 'App' 컴포넌트의 하위 트리(여기서는 Sub1)에 새로운 테마 값을 제공합니다.
    // 이 Provider 덕분에 Sub1은 'blue' 테마를 받게 됩니다.
    <themeContext.Provider value={{ border: '10px solid blue' }}>
      {/* 가져온 테마 값을 div의 스타일에 적용합니다. (이 div에는 'red' 테마가 적용돼요.) */}
      <div className="root" style={theme}>
        <h1>Hello World</h1>
        {/* Sub1 컴포넌트를 렌더링합니다. Sub1은 여기 Provider에서 제공하는 'blue' 테마를 받게 될 거예요. */}
        <Sub1 />
      </div>
    </themeContext.Provider>
  );
}

test

 


Completion

import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import { createContext, useContext } from 'react';

const themeDefault = { border: '10px solid red' };
const themeContext = createContext(themeDefault);

function Sub1() {
  const theme = useContext(themeContext);
  return (
    <themeContext.Provider value={{ border: '10px solid green' }}>
      <div style={theme}>
        <h1>Sub1</h1>
        <Sub2 />
      </div>
    </themeContext.Provider>
  );
}

function Sub2() {
  const theme = useContext(themeContext);
  return (
    <div style={theme}>
      <h1>Sub2</h1>
      <Sub3 />
    </div>
  );
}

function Sub3() {
  const theme = useContext(themeContext);
  return (
    <div style={theme}>
      <h1>Sub3</h1>
    </div>
  );
}

export default function App() {
  const theme = useContext(themeContext);
  console.log('theme', theme);
  return (
    <themeContext.Provider value={{ border: '10px solid blue' }}>
      <div className="root" style={theme}>
        <h1>Hello World</h1>
        <Sub1 />
      </div>
    </themeContext.Provider>
  );
}

 



출처

https://wikibook.co.kr/react-rev-ebook/

 

생활코딩! React 리액트 프로그래밍 (개정판) (ebook): 처음 프로그래밍을 시작하는 입문자의 눈높이

세상에서 리액트를 가장 쉽게 설명한 입문서! 생활코딩은 일반인에게 프로그래밍을 알려주는 것을 목적으로 하는 비영리 교육 활동입니다. 이 책은 생활코딩에서 제공하는 수업 가운데 리액트

wikibook.co.kr