본문 바로가기
Programming/React.js

12. ContextApi

by _S0_H2_ 2022. 9. 14.
728x90
반응형

기존 컴포넌트간에 상태를 교류해야할 때 무조건 부모 -> 자식 흐름으로 props를 통해 전달하였는데, 이제는 ContextAPI를 통해 더 쉽게 상태를 교류할 수 있다. 프로젝트 컴포넌트 구조가 간단하고 다루는 상태 종류가 많지 않다면 Context를 사용할 필요는 없지만 전역적으로 사용되는 상태가 있고 컴포넌트 개수가 많은 상황에서 유용하게 사용할 수 있다.

아래에서 App-H-J , App-A-B-F, App-A-B-E-G 로 접근하던 것을 바로 접근할 수 있다.

Consumer


우선 프로젝트를 새로 생성한다.

yarn create react-app context-tutorial

다음 파일들을 생성한다.

- src/contexts/color.js

import {createContext} from 'react';
const ColorContext = createContext({color : 'black'});
export default ColorContext;

여기에서 생성하는 ColorContext를 소비자를 통해 color에 접근할 수 있다.

- src/components/ColorBox.js

import ColorContext from '../contexts/colors';

const ColorBox = () => {
    return(
        <ColorContext.Consumer>
        {value => (
            <div
                style = {{
                    width: '64px',
                    height: '64px',
                    background: value.color
                }}
            />
        )}
        </ColorContext.Consumer>
    );
};

export default ColorBox;

위에서 만든 ColorContext.Consumer에서 위에서 생성한 객체를 value로 받아 value.color로 접근할 수 있다.

-app.js

import ColorBox from './components/colorBox.js';

const App = () =>{
  return(
    <div>
      <ColorBox />
    </div>
  )
}

export default App;

실행하면 다음과 같이 나타난다.

Provider

provider를 사용하면 Context의 value를 변경할 수 있다.

import ColorBox from './components/colorBox';
import ColorContext from './contexts/colors';


const App = () =>{
  return(
    <ColorContext.Provider value={{color:'red'}}>
    <div>
      <ColorBox />
    </div>
    </ColorContext.Provider>
  )
}

export default App;

Provider를 사용할 때는 value를 명시하지 않으면 에러가 난다!!

위의 내용이 고정적인 값들만 사용한 경우라면, 업데이트를 하는 경우도 있다.
함수를 넣을 수 있는데 다음과 같이 변경해볼 수 있다.

- contexts/colors.js

import {createContext, useState} from 'react';
const ColorContext = createContext({
    state: {color : 'black', subcolor:'red'},
    actions: {
        setColor: () => {},
        setSubColor: () => {}
    }
});

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>
    );
};

const {Consumer: ColorConsumer } = ColorContext;
export {ColorProvider, ColorConsumer};

//export default ColorContext;

ColorProvider에서 ColorContext.Provider를 렌더링하면서 Provider의 value에 상태(state)와 업데이트함수(actions)를 묶어서 전달하고 있다.

- components/ColorBox.js

import {ColorConsumer} from '../contexts/colors';

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

export default ColorBox;

- App.js

import ColorBox from './components/colorBox';
import {ColorProvider} from './contexts/colors';


const App = () =>{
  return(
    <ColorProvider>
    <div>
      <ColorBox />
    </div>
    </ColorProvider>
  )
}

export default App;

현재까지는 정한 값을 보여주는데, Context의 actions에 있는 함수를 호출하는 컴포넌트를 만들 수 있다.
- components/SelectColors.js

import {ColorConsumer} from '../contexts/colors';

const colors = ['red', 'orange', 'yellow', 'green', 'blue']
const SelectColors = () => {
    return(
        <div>
            <h2> 색상을 선택하세요 </h2>
            <ColorConsumer>
            {({actions}) => (
                <div 
                    style={{display:'flex'}}>{
                    colors.map(color => (
                        <div 
                            key = {color}
                            style = {{
                            background: color,
                            width:'24px',
                            height:'24px',
                            cursor:'pointer'
                        }}
                        onClick={() => actions.setColor(color)}
                        onContextMenu={e => {
                            e.preventDefault();
                            actions.setSubColor(color);
                        }}
                        />
                    ))}
                </div>
            )}
            </ColorConsumer>
            <hr />
        </div>
    );
};
export default SelectColors;

- App.js

import ColorBox from './components/colorBox';
import {ColorProvider} from './contexts/colors';
import SelectColors from './components/selectColors';

const App = () =>{
  return(
    <ColorProvider>
    <div>
      <SelectColors />
      <ColorBox />
    </div>
    </ColorProvider>
  )
}

export default App;

색을 선택하면 색이 변경된다!

이를 좀 더 간결하게 사용하기 위해 useContext Hook을 사용할 수도 있다.

-components/ColorBox.js

import {useContext} from 'react';
import ColorContext from '../contexts/colors';

const ColorBox = () => {
    const {state} = useContext(ColorContext);
    return(
            <>
            <div
                style = {{
                    width: '64px',
                    height: '64px',
                    background: state.color
                    
                }}
            />
            <div
                style = {{
                    width: '32px',
                    height: '32px',
                    background: state.subColor
                }}
            />
        </>
    );
};

export default ColorBox;

728x90
반응형

'Programming > React.js' 카테고리의 다른 글

14. Redux로 React app 상태 관리  (0) 2022.10.26
13. Redux  (0) 2022.09.17
11. 라우터로 SPA 개발하기  (0) 2022.09.08
10. immer사용하여 불변성 유지하기  (0) 2022.08.31
9. 컴포넌트 성능 최적화  (0) 2022.08.24