15. Context API

히치키치·2022년 1월 6일
0

React_Advance

목록 보기
3/9
post-thumbnail

✔ 전역 상태 관리 흐름 이해

  • 여러 컴포넌트를 거쳐 props 사용 시 기존의 top->bottom 흐름으로 많은 컴포넌트 거치거나 데이터가 많아지는 경우 유지 보수성 낮아짐
  • Context 만들어 한번에 원하는 값 받아옴

✔ Context API 사용법

1. 새로운 Context 생성

  • createContext 함수를 사용해 Context 생성
  • 파라미터로 해당 Context 기본 상태 지정
import {createContext} from "react";
const ColorContext=createContext({color:"black"}); //기본 상태 색상 : 검정
export default ColorContext;

2. Consumer 사용

  • ColorBox 컴포넌트 만들어 ColorContext 안에 있는 색상 불러옴
  • props가 아닌 ColorContext 안에 Consumer 컴포넌트 사용
  • Render Props : Consumer 사이에 중괄호 열어 그 안에 함수 넣음
import React from 'react';
import ColorContext from '../contexts/color';

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

export default ColorBox;

3. App에서 랜더링

import './App.css';
import ColorBox from './component/ColorBox';

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

export default App;

4. Provider 사용

  • Provider 사용해 Context의 value 변경
  • Provider 사용하고 value 명시 안하면 오류 발생
import logo from './logo.svg';
import './App.css';
import ColorBox from './component/ColorBox';
import ColorContext from './contexts/color';

const App=()=>{
  return (
    <ColorContext.Provider value={{color:"red"}}> 
    {/*provider를 사용한 value 변경*/}
      <div>
        <ColorBox/>
      </div>
    </ColorContext.Provider>
  );
};

export default App;

✔ 동적 Context 사용

1. 함수 전달하는 Context

  • 새로 작성한 ColorProvider 컴포넌트에 ColorContext.Provider 랜더링
  • Provider의 value에 상태(state), 업데이트 함수(actions) 분리해서 묶어서 전달하면 다른 컴포넌트에 Context 값 사용할 때 편함
import {createContext, useState} from "react";

const ColorContext=createContext({
    state:{color:"black", subcolor:"red"},
    actions:{
        setColor:()=>{},
        setSubcolor:()=>{}
    }
});


const ColortProvider=({children})=>{
    const [color,setColor]=useState("black");
    const [subcolor,setSubcolor]=useState("red");

    const value={
        state:{color,subcolor}, //상태
        actions:{setColor,setSubcolor} //업데이트 함수
    };

    return (
      //상태와 업데이트 함수 따로 분리하여 작성하여 
      //ColorContext.Provider에 넣는 객체의 형태와 일치 하는 것이 좋음
      <ColorContext.Provider value={value}>
      	{children}			
	</ColorContext.Provider>);
};

//const ColorConsumer =ColortContext.Consumer
const {Consumer:ColorConsumer}=ColorContext;

//ColorProvider와 ColorConsumer 내보내기
export {ColortProvider,ColorConsumer};

export default ColorContext;

2. 새로운 Context 프로젝트 반영

  • App 컴포넌트에서 ColorContext.Provider -> ColorProvider
import './App.css';
import ColorBox from './component/ColorBox';
import { ColortProvider } from './contexts/color';

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

export default App;
  • ColorBox 컴포넌트에서 ColorContext.Consumer -> ColorConsumer
  • 객체 비구조화 할당 문법 사용해 value.state.color -> state.color
import React from 'react';
import { ColorConsumer } from '../contexts/color';

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

            }

        </ColorConsumer>
    );
};

export default ColorBox;

3. 컬러 선택 팔레트 UI

import React from 'react';

const colors=["red","orange","yellow","green","blue","indigo","violet"];

const SelectColors=()=>{

    return (
        <div>
            <h2> 색상을 선택하세요.</h2>
            <div style={{display:"flex"}}>
                {colors.map(color=>(
                    <div key={color}
                    style={{
                        background:color,
                        width:"24px",
                        height:"24px",
                        cursor:"pointer"
                    }}/>
                ))}
            </div>
            <hr/>
        </div>
    );
};

export default SelectColors;
import './App.css';
import ColorBox from './component/ColorBox';
import { ColortProvider } from './contexts/color';
import SelectColors from './component/SelectColors';

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

export default App;

4. 컬러 팔레트 클릭으로 색상 변경

  • 마우스 왼쪽 클릭 : 큰 정사각형 색상 변경
  • 마우스 오른쪽 클릭 : 작은 정사각형 색상 변경
import React from 'react';
import { ColorConsumer } from '../contexts/color';

const colors=["red","orange","yellow","green","blue","indigo","violet"];

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;

✔ Consumer 대신 Hook / static contextType 사용

1. useContext Hook 사용

함수형 컴포넌트에서만 사용 가능, 클래스형에서는 사용 불가능

  • Render Props 패턴보다 간편한 작성법
import React, { useContext } from 'react';
import ColorContext from '../contexts/color';

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;

2. static contextType 사용

  • 클래스형 컴포넌트에서 Context 사용
  • static contextType 정의해 Context의 함수 호출 가능
  • 한 클래스에서 한개의 Context만 사용 가능

useContext Hook 사용

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

const colors=["red","orange","yellow","green","blue","indigo","violet"];

class SelectColors extends Component{ //클래스형으로 작성

    //static contextType 지정
    static contextType=ColorContext;


    //this.context 조회 = 현재 context의 value 가르킴
    handleSetColor=color=>{
        this.context.actions.setColor(color); //setcolor 호출
    };

    handleSetSubcolor=subcolor=>{
        this.context.actions.setSubcolor(subcolor); //setSubcolor 호출
    }
    render(){
        return (
            <div>
                <h2>색상 선택</h2>
                <div style={{display:'flex'}}>
                    {colors.map(color=>(
                        <div 
                            key={color}
                            style={{
                                background:color,
                                width:"24px",
                                height:"24px",
                                cursor:"pointer"
                            }}
                            onClick={()=>this.handleSetColor(color)}
                            onContextMenu={e=>{
                                e.preventDefault();
                                this.handleSetSubcolor(color);
                            }}
                        />
                    ))}
                </div>
                <hr/>
            </div>
        );
    }
}

export default SelectColors;

0개의 댓글