네이버 클라우드 캠프/React

[React] Context API

graph-dev 2023. 7. 27. 20:24
728x90

 

react logo

context API

맥락 API가 무엇일까요?

react 앱을 만들게 되면 가장 중요한 것은 상태 값을 관리하는 것입니다. 컴포넌트가 많아지고 그 사이에 관계가 많아지면 구조가 복잡해집니다. 이 때, 전역(global)하게 상태를 관리해주는 API가 필요합니다. 그 역할을 해주는 것이 context API입니다.

 

 

context API 예제

//createContext() 메소드를 이용해서 context를 생성
const context명(컴포넌트처럼 사용하기 때문에 첫글자를 대문자로) = createContext(context의 초기값);
createContext(context의 초기값);

//Provider로 context의 데이터를 제공
<context명.Provider value={제공할 데이터}>
    <context를 사용할 컴포넌트들>
</context명.Provider>

//Consumer로 제공받은 데이터 사용
//context를 사용할 컴포넌트에서 사용한다
<context명.Consumer>
    {value =>
        <컴포넌트나 태그>
    }
</context명.Consumer>

 

createContext

createContext는 context를 만들어주는 메소드입니다. 초기값을 지정해야합니다.

 

생성된 context에는 Provider와 Consumer가 소유하고 있습니다. Provider는 value라는 키를 통해 context의 값을 바꿀 수 있습니다. Consumer는 value를 통해 Provider에서 제공하는 새로운 값을 사용할 수 있습니다.

 

예제를 통해 알아보겠습니다.

아래 예제는 여러 색상의 상자를 붙여서 색상을 선택하면, 아래 큰 박스하나와 작은 박스의 색상이 변화되게 만들었습니다.

 

먼저 색상표에 표출할 색상을 배열합니다. colorArr를 생성해두고, SelectColor를 만들고 화살표 함수를 통해 리턴값을 정의합니다.

import React from 'react'
import { ColorConsumer } from '../contexts/color';

//색상 표에 표출할 색상 배열
const colorArr = ['black', 'red', 'green', 'blue', 'yellow', 'orange', 'gray', 'violet'];

const SelectColor = () => {
  return (
    <div>
        <h1>색상 선택</h1>
        <ColorConsumer>
            {({actions}) => (
                <div style={{display: 'flex'}}>
                    // index받아서 처리해도 된다.
                    // props 전달 하나도 없이 state 값을 바꾼다.
                    (color, index) => (
                        <div key={index} style={{width: '25px', height: '25px', background: color, cursor: 'pointer'}} 
                        onClick={() => actions.setColor(color)} 
                        onContextMenu={(e) => {
                            e.preventDefault(); //우클릭시 메뉴 안뜨도록 만든다.
                            actions.setSubColor(color);
                        }}></div>
                    )
                )}
            </div>
            )}
        </ColorConsumer>
        <hr></hr>
    </div>
  )
}

export default SelectColor

 

 

ColorConsumer가 어떻게 되어있을지 궁금합니다. 이 때 사전 정의된 contexts 내에 color.js 파일을 확인해봅니다. createContext 메서드를 통해 우리가 Provider와 Consumer를 만들 수 있습니다. 전달할 두가지 파라미터를 정의합니다. Color가 위에 있는 상자고, subColor는 바로 밑에 붙은 작은 상자의 색상으로 정의합니다.

//createContext로 생성한 context를 export한다.
import {createContext, useState} from 'react';

//context 생성
//Provider, Consumer를 소유
const ColorContext = createContext({
    state: {color: 'black', subColor: 'red'},
    actions: {
        setColor: () => {},
        setSubColor: () => {}
    }
});

//...
export default ColorContext;

 

다음은 Provider 리턴하는 컴포넌트입니다. 보시면 children이라는 파라미터를 설정해두고, color, subColor의 초기값을 각각 검정, 빨강으로 설정합니다. 그 이후에 state, actions를 값으로 잡고 children으로 한꺼번에 그 값을 반환해줍니다.

//Provider를 리턴하는 컴포넌트
const ColorProvider = ({children}) => {
    const [color, setColor] = useState('black');
    const [subColor, setSubColor] = useState('red');

    const value = {
        state: {color, subColor},
        actions: {setColor, setSubColor}
    }

    return <ColorContext.Provider value={value}>{children}</ColorContext.Provider>
}

Consumer를 반환하는 컴포넌트는 다음과 같습니다. ColorConsumer는 ColorContext.Consumer를 의미합니다. 이 때는 아래와 같이 표현할 수 있습니다. export를 통해 Provider, Consumer를 함께 묶어 반환합니다.

//Consumer 리턴하는 컴포넌트
//ColorConsumer == ColorContext.Consumer 같다고 가정.
const {Consumer: ColorConsumer} = ColorContext;

export {ColorProvider, ColorConsumer};

export default ColorContext;

ㅁ마지막은 ColorBox로 색상표를 정의한 부분입니다. value라는 변수로 value.state.color를 호출할 수 있습니다. 바로 적용될 수 있게 전역 컴포넌트인 ColorConsumer를 업데이트합니다.

import React from 'react';
import {ColorConsumer} from '../contexts/color';

const ColorBox = () => {
  return (
    <ColorConsumer>
        {value => (
            <div>
                <div style={{width: '100px', height: '100px', background: value.state.color}}></div>
                <div style={{width: '50px', height: '50px', background: value.state.subColor}}></div>
            </div>
        )}
    </ColorConsumer>
  );
};

export default ColorBox;

만약에 우리가 value.state를 좀 더 줄이고 싶다면, value 대신 {state}를 하나의 매개변수로 만들어서 바꿀 수 있습니다. state가 value.state를 말한다고 표현할 수 있는거죠.

{({state}) => (
    <div>
        <div style={{width: '100px', height: '100px', background: state.color}}></div>
        <div style={{width: '50px', height: '50px', background: state.subcolor}}></div>
    </div>
)}

이렇게 하면 value.state.color 를 state.color로 줄여볼 수 있어서 깔끔합니다.

 

이제 App.js에서 위의 생성한 context와 컴포넌트를 호출하면 됩니다.

import ColorBox from "./components/ColorBox";
import SelectColor from "./components/SelectColor";
import {ColorProvider} from "./contexts/color";

function App() {

  return (
    //<ColorContext.Provider value={값}>
    <ColorProvider>
      <div>
        <SelectColor></SelectColor>
        <ColorBox></ColorBox>
      </div>
    </ColorProvider>    
  );
}

export default App;

return 값에서 드디어 ColorProvider가 나오고, 그 내부에서 ColorConsumer에서 정의한 SelectColor 컴포넌트와 ColorBox가 호출됩니다. 이 두 컴포넌트는 각각 색상표와 ColorBox(Color, SubColor가진 상자 2개)를 화면에 표출하게 됩니다.

 

여기서 잠시 색상표를 클릭하게 되면 아래 상자(ColorBox) 색상이 변하도록 하는 코드를 잠깐 살펴보겠습니다. onClick 이후에 발생할 행동을 정의했습니다. index를 통해 색상표에 담은 색상 값을 setColor로 하단 큰 상자 색상에 적용하도록 합니다. 그리고 우클릭을 하면 actions.setSubColor로 작은 상자의 색이 변하게 만들었습니다.

{({actions}) => (
    <div style={{display: 'flex'}}>
        {colorArr && colorArr.map(
            (color, index) => (
                <div key={index} style={{width: '25px', height: '25px', background: color, cursor: 'pointer'}} 
                onClick={() => actions.setColor(color)} 
                onContextMenu={(e) => {
                    e.preventDefault(); //우클릭시 메뉴 안뜨도록 만든다.
                    actions.setSubColor(color);
                }}></div>
            )
	    )}
	</div>
)}

그런데 색상표에 있는 색상은 서로 겹치는 것이 없죠. 중복이 없으므로 이 색상(color)자체를 인덱스 대신 키 값으로 사용할 수도 있습니다. 화살표 함수를 통해 이 color값을 전달하면서도, 서로 구분짓는 인덱스 값도 사용가능합니다.

{({actions}) => (
                <div style={{display: 'flex'}}>
                    {colorArr && colorArr.map(
                    // 고유한 color만으로 key 값을 넣는다.
                    color => (
                        <div key={color} style={{width: '25px', height: '25px', background: color, cursor: 'pointer'}}>
                            onClick={() => actions.setColor(color)} 
                            onContextMenu={(e) => {
                                e.preventDefault(); //우클릭시 메뉴 안뜨도록 만든다.
                                actions.setSubColor(color);
                    	}}></div>
                    )
                )}

 

 

 

'네이버 클라우드 캠프 > React' 카테고리의 다른 글

[React] axios로 뉴스 앱 만들기(1)  (0) 2023.08.02
[React] JWT와 CORS  (0) 2023.07.28
[React] Immersion  (0) 2023.07.20
[React] Component Styling  (0) 2023.07.20
[React] Hooks(2)  (0) 2023.07.20