본문 바로가기
개발/React

리액트 - Context API로 상태 관리하기 (Managing State with Context API)

by 피로물든딸기 2024. 3. 15.
반응형

리액트 전체 링크

 

참고

- 리덕스로 상태 관리하기

- Context API로 상태 관리하기
- recoil로 상태 관리하기
SWR로 상태 관리하기

 

propsuseState에 정의된 값을 넘겨주면, 하위 컴포넌트에서 상태를 관리할 수 있다.

예시 코드는 다음과 같다.

// ParentComponent.js
import React, { useState } from "react";
import ChildComponent from "./ChildComponent";

const ParentComponent = () => {
  const [value, setValue] = useState(0);
  return (
    <div>
      <h2>Parent Component</h2>
      <button onClick={() => setValue(value + 1)}>Parent +</button>
      <p>{`Parent value : ${value}`}</p>
      <ChildComponent value={value} setValue={setValue} />
    </div>
  );
};

export default ParentComponent;

 

자식 컴포넌트는 다음과 같다.

// ChildComponent.js
import React from 'react';
import GrandChildComponent from './GrandChildComponent';

const ChildComponent = ({ value, setValue }) => {
  return (
    <div>
      <h3>Child Component</h3>
      <button onClick={() => setValue(value + 1)}>Child +</button>
      <p>{`Child value : ${value}`}</p>
      <GrandChildComponent value={value} setValue={setValue}/>
    </div>
  );
}

export default ChildComponent;

 

손자 컴포넌트는 다음과 같다.

// GrandChildComponent.js
import React from 'react';

const GrandChildComponent = ({ value, setValue }) => {
  return (
    <div>
      <h4>Grandchild Component</h4>
      <button onClick={() => setValue(value + 1)}>Grandchild +</button>
      <p>{`Grandchild value : ${value}`}</p>      
    </div>
  );
}

export default GrandChildComponent;

 

이제 value가 모든 컴포넌트에서 연동된다.

 

만약 ChildComponent value에 대한 상태를 알 필요가 없거나, 하이어라키가 복잡해지면 상태 관리가 어려워진다.


Context API 적용하기

 

이제 ChildComponent에는 value가 필요 없다고 가정하고 Context API로 상태를 관리해 보자.

 

createContext를 이용해서 아래와 같이 valuesetValue를 정의하는 Provider를 생성한다.

// AppContext.js
import React, { createContext, useState, useContext } from 'react';

const AppContext = createContext();

export const useAppContext = () => useContext(AppContext);

export const AppProvider = ({ children }) => {
  const [value, setValue] = useState(0);

  return (
    <AppContext.Provider value={{ value, setValue }}>
      {children}
    </AppContext.Provider>
  );
};

 

Provider가 필요한 가장 상위의 Component(= Parent)에 아래와 같이 Provider 컴포넌트를 추가한다.

(꼭 전역일 필요가 없다. 필요한 Component의 상위에 추가하면 된다.)

// App.js
import React from "react";
import ParentComponent from "./ParentComponent";
import { AppProvider } from "./AppContext";

const App = () => {
  return (
    <div className="App">
      <AppProvider>
        <ParentComponent />
      </AppProvider>
    </div>
  );
};

export default App;

 

이제 ParentComponentprops를 넘겨 받지 않고, useAppContextstate를 관리한다.

// ParentComponent.js
import React from "react";
import { useAppContext } from "./AppContext";
import ChildComponent from "./ChildComponent";

const ParentComponent = () => {
  const { value, setValue } = useAppContext();
  
  return (
    <div>
      <h2>Parent Component</h2>
      <button onClick={() => setValue(value + 1)}>Parent +</button>
      <p>{`Parent value : ${value}`}</p>
      <ChildComponent />
    </div>
  );
};

export default ParentComponent;

 

ChildComponent는 상태를 관리하지 않는다.

// ChildComponent.js
import React from 'react';
import GrandChildComponent from './GrandChildComponent';

const ChildComponent = () => {
  return (
    <div>
      <h3>Child Component</h3>
      <GrandChildComponent />
    </div>
  );
}

export default ChildComponent;

 

GrandChildComponentParent와 마찬가지로 useAppContext를 이용한다.

// GrandChildComponent.js
import React from 'react';
import { useAppContext } from './AppContext';

const GrandChildComponent = () => {
  const { value, setValue } = useAppContext();
  
  return (
    <div>
      <h4>Grandchild Component</h4>
      <button onClick={() => setValue(value + 1)}>Grandchild +</button>
      <p>{`Grandchild value : ${value}`}</p>      
    </div>
  );
}

export default GrandChildComponent;

 

이제 ChildComponent value를 넘겨받지 않아도 GrandChildComponent는 정상적으로 상태를 관리한다.

반응형

댓글