Context API

Jaeseok Han·2023년 11월 9일
0

React Basic

목록 보기
23/30

Context API

Challenge

  • 세 개의컴포넌트를 만들고 다음과 같이 구성한다.
  • Navbar.jsx
    • NavLinks.jax(Navbar 내에 위치)
      • Usercontainer.jsx(NavLink 내에 위치)
  • App.jsx 에서 Navbar.jsx 를 가져온다.(컨테이너 스타일은 제거)
  • Navbar.jsx 설정
    • user 상태값 생성
      • 기본값은 {name : 'somthing'}
    • 로그아웃 함수 생성
      • user를 다시 null로 설정
  • 이 두 값을 UserContainer로 전달
  • user 정보와 버튼을 표시
  • 버튼 클릭 시 user를 다시 null로 설정
  • 추가 도전 과제
    • 사용자가 null 이라면 UserContainer에 <p>please login</p> 을 표시

풀이

Navbar.jsx, NavLinks.jsx, UserContainer.jsx 생성
Navbar.jsx

import React, { useState } from 'react'
import NavLinks from './NavLinks'

const Navbar = () => {
  const [user, setUser] = useState({name : 'bob'})
  const logout = () => {
      setUser(null)
  }
  return (
    <nav className='navbar'>
        <h5>CONTEXT API</h5>
        <NavLinks user={user} logout={logout}/>
    </nav>
  )
}

export default Navbar

NavLinks.jsx

import React from 'react'
import UserContainer from './UserContainer'

const NavLinks = ({user, logout}) => {
  return (
    <div className='nav-container'>
        <ul className="nav-links">
            <li>
                <a href="#">home</a>
            </li>
            <li>
                <a href="#">about</a>
            </li>
        </ul>
        <UserContainer user={user} logout={logout}/>
    </div>
  )
}

export default NavLinks

UserContainer.jsx

import React, { useState } from 'react'

const UserContainer = ({user, logout}) => {
  return (
    <div className='user-container'>
        {user ? (
            <>
                <p>Hello There, {user?.name?.toUpperCase()}</p>
                <button className='btn' onClick={logout}>
                    logout
                </button>
            </>
        )  : (
            <p>Please Login</p>
        )}
    </div>
  )
}

export default UserContainer

Prop drilling

import React, { useState, createContext, useContext } from 'react'
import NavLinks from './NavLinks'

export const NavbarContext = createContext();

// custom hook

export const useAppContext = () => useContext(NavbarContext)

const Navbar = () => {
  const [user, setUser] = useState({name : 'bob'})
  const logout = () => {
      setUser(null)
  };
  
  return (
    <NavbarContext.Provider value={{user, logout}}>
      <nav className='navbar'>
          <h5>CONTEXT API</h5>
          <NavLinks user={user} logout={logout}/>
      </nav>
    </NavbarContext.Provider>
  )
}

export default Navbar

import React, { useContext, useState } from 'react'
import { NavbarContext, useAppContext } from './Navbar';

const UserContainer = () => {
    const {user, logout} = useAppContext();
    // const {user, logout} = useContext(NavbarContext);

    return (
        <div className='user-container'>
            {user ? (
                <>
                    <p>Hello There, {user?.name?.toUpperCase()}</p>
                    <button className='btn' onClick={logout}>
                        logout
                    </button>
                </>
            )  : (
                <p>Please Login</p>
            )}
        </div>
  )
}

export default UserContainer

import React, { useContext } from 'react'
import UserContainer from './UserContainer'
import { NavbarContext, useAppContext } from './Navbar'

const NavLinks = () => {
  const {user, logout} = useAppContext();
console.log(user)
  return (
    <div className='nav-container'>
        <ul className="nav-links">
            <li>
                <a href="#">home</a>
            </li>
            <li>
                <a href="#">about</a>
            </li>
        </ul>
        <UserContainer user={user} logout={logout}/>
    </div>
  )
}

export default NavLinks

Context API

Context API를 사용하면 상태나 데이터를 상위 컴포넌트에서 하위 컴포넌트로 계속 props로 전달하지 않고 공유가능하다. 특히 계층 구조로된 컴포넌트 구조에서 데이터를 효율적으로 공유할 수 있다.

  • 중앙 집중화된 상태 관리
  • 계층 구조로 구성된 컴포넌트 간의 편리한 데이터 공유
  • 컴포넌트 간의 결합 감소
  • 글로벌 상태 관리

Setup Global Context

  1. 새로운 프로젝트 설정
npm create vite@latest global-context -- --template react
  1. 프로젝트 설치 밎 시작
cd global-context
npm install && npm run dev
  • context.jsx 파일 생성
    src 폴더 안에 context.jsx 파일을 생성합니다.
  • 글로벌 컨텍스트 설정 - GlobalContext
  • 컴포넌트 설정 (AppContext) 및 상태 값 추가
  • AppContext 컴포넌트를 만들고, 그 안에서 하나의 상태 값을 설정합니다. 이 상태 값을 GlobalContext.Provider 컴포넌트 내에서 반환합니다.
    AppContext에서 GlobalContext.Provider 반환
  • 전체 애플리케이션(main.jsx)을 감싸기
    children prop "gotch"
  • 커스텀 훅 설정
  • App.jsx에서 액세스 및 결과 로깅

context.js

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

const GlobalContext = createContext();

export const useGlobalContext = () => useContext(GlobalContext);

const AppContext = ({children}) => {
    const [name, setName] = useState('JS');
    return <GlobalContext.Provider value={{name, setName}}>
        {children}
    </GlobalContext.Provider>
}

export default AppContext;

main.js

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
import AppContext from './context.jsx'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <AppContext>
      <App />
    </AppContext>
  </React.StrictMode>,
)

App.jsx

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

function App() {
  const [count, setCount] = useState(0)
  const {name} = useGlobalContext();
  console.log(name);

  return (
    <>

    </>
  )
}

export default App

GlobalContext를 전역에서 사용가능하도록 데이터를 담아서 사용한다.

0개의 댓글