[React.js] context API(Feat. useContext)

25892 단어 ReactstudyReact

context API?

전역적인 상태 관리를 위한 기능

React를 이용하여 개발 시, 부모 컴포넌트에서 자식 컴포넌트로 데이터를 보낼 때, props를 사용한다.

하지만 개발 중인 애플리케이션 규모가 매우 커서 페이지 개수가 많아 컴포넌트의 깊이(depth)가 깊을 때, 전달해야 할 props의 개수가 많을 때, props만 이용하기에는 매우 부담이 된다.

그래서 값을 전역적으로 관리할 수 있는 context API, 상태 관리 라이브러리(Redux, MobX 등)를 많이 사용하는데, 이번에는 context API에 관한 내용을 공부하였다.

props의 단점

위에서 언급했듯이, 컴포넌트의 깊이가 깊을 때 곤욕을 치를 수 있다.

위의 그림 처럼 A 컴포넌트는 c, d, B 하위 컴포넌트를 가지고 있는데, A에서 B로 data 변수를 props로 보내주려면 c와 d를 거쳐서 B로 전달하게 된다.

c, d 컴포넌트는 data를 사용하지 않지만 props를 받아야하고 전달자 역할을 해야한다.

따라서 간단한 애플리케이션이면 모르겠지만, 컴포넌트의 깊이가 깊은 경우, props를 이용하면 유지보수에도 어려움이 있을 수 있다.

이러한 단점을 보완할 수 있는 기능이 context API 이다.

context API의 전역 상태 관리 흐름

위 그림의 의미는 A 컴포넌트에 context를 연결하면 A 컴포넌트의 하위 컴포넌트들은 context에 보관 되어있는 값(변수, state, 함수 등)에 직접적으로 접근해서 사용할 수 있다는 것이다.

예제 코드 (Feat. useContext)

컴포넌트 구조

최상위 컴포넌트인 app.js가 있으며, 하위 컴포넌트로는 About.js, PersonName.js가 있고, PersonName.js의 하위 컴포넌트로는 Job.js가 있다.

  1. app.js
import About from './components/About';
import PersonName from './components/PersonName';

function App() {

  return (
    <>
    <PersonProvider>
      <About></About>
      <PersonName></PersonName>
      </PersonProvider>
    </>
    
  );
}

export default App;

context 생성

context 폴더를 만들고 그 안에 PersonProvider.js 파일을 생성한다.

  • PersonProvider.js
import React, { useState, createContext } from 'react';

export const personContext = createContext();

const PersonProvider = ({ children }) => {
    const [personNames, setPersonNames] = useState('홍길동');
    const [about, setAbout] = useState('나는 의적이다.');
    const [job, setJob] = useState('의적');
    let temp = 'temp'

    const printalert = (names) => {
        alert(names);
    }

    const value = {
        state: {personNames, about, job, temp},
        actions : {setPersonNames, setAbout, setJob, printalert}
    }

    return (<personContext.Provider value={value}>{children}
      </personContext.Provider>)
}

export default PersonProvider;

PersonProvider 컴포넌트에 state, setState함수, 일반 변수, 일반 함수 등을 선언했다. 그리고 이것들을 value 객체에 state, actions 객체에 담았다.

PersonProvider 바깥에 personContextcreateContext()를 이용하여 context를 반환할 수 있도록 하였고, PersonProvider 컴포넌트에서는 personContext.Provider를 리턴한다.

이렇게 context를 만들 수 있다.

context API 적용

  1. app.js
import './App.css';

import About from './components/About';
import PersonName from './components/PersonName';
import PersonProvider from './contexts/PersonProvider';


function App() {

  return (
    <>
    <PersonProvider>
      <About></About>
      <PersonName></PersonName>
      </PersonProvider>
    </>
    
  );
}

export default App;

context에 직접 접근하고자 하는 컴포넌트들을 PersonProvider의 children으로 두었다.

  1. About.js
import React, { useContext } from 'react';
import Job from '../components/Job';
import { personContext } from '../contexts/PersonProvider';

const About = () => {
    const context = useContext(personContext);

    const change = () => {
        context.actions.setAbout("context change");
    }

    return(
        <div className='About'>
            {context.state.about}
            <button onClick={change}>change</button>
            <Job></Job>
        </div>
    )
}

export default About;
  1. PersonName.js
import React, { useContext } from 'react';
import { personContext } from '../contexts/PersonProvider';


const PersonName = () => {
    const context = useContext(personContext);

    const change = ()=> {
        context.actions.setPersonNames('change the person Name');
    }
    return(
        <div className='PersonName' onClick={change}
          style={{cursor:'pointer'}}>
            {context.state.personNames}
        </div>
    )
}

export default PersonName;
  1. Job.js
import React, { useContext } from 'react';
import { personContext } from '../contexts/PersonProvider';

const Job = () => {
    const context = useContext(personContext);

    const change = () => {
        context.actions.setJob('changed the job');
        context.actions.printalert(context.state.job);
    }
    return(
        <div className='Job'>
            {context.state.job}
            {context.state.temp}
            <button onClick = {change}>chage</button>
        </div>
    )
}

export default Job;

context를 전역적으로 사용하는 방법

위에서 언급하였듯이, 임의의 컴포넌트와 context를 연결하면 연결된 컴포넌트의 하위 컴포넌트들이 context에 직접 접근하여 사용할 수 있다.

따라서 전역적으로 context를 사용하려면 index.js의 root 컴포넌트를 Provider로 감싸야한다.

//root index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { PersonProvider } from './store.js';

ReactDOM.render(
  <PersonProvider>
    <App/>
  </PersonProvider>,
  document.getElementById("root")
);

좋은 웹페이지 즐겨찾기