Context API 시도

nevermind·2022년 9월 1일
0
post-custom-banner

인스타 클론코딩 때 많은 모달창들을 다 props로 전달하니 너무 복잡하고 협업하는 팀원도 힘들어했었다.

기술 매니저님께 추천받은 Context API를 시도해보고자 찾아보고 시도해봤는데 모달창은 어떻게 구현하는지 잘 모르겠어서 조금 헤매는 시간을 가졌다ㅠㅠ

큰 도움을 받은 블로그 : https://leedr0730.medium.com/react-context-api%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-5d2f95d67b09
큰 도움 받은 유튜브 : youtube.com/watch?v=sqz45pnvJHg

블로거의 코드샌드박스를 보며 따라치니 실행이 되었다ㅠㅠㅠ
props 몇 단계를 건너건너 갔던 시절이여 이제 안니영~~

윗사진은 코드 최상단의 App.js이다. 많은 useState들을 뿌려주었다. props를 타고타고 와서 App.js에 오면 이게 어디서 열리는지 못찾는 문제들이 많았다 @.@

사용방법

  • Context는 별도의 설치가 필요 없다
  • Context를 사용하기 위해서는 Context와 Provider,Consumer이 필요하다
  • Context 객체 만들기(리덕스에서 Store와 같은 역할)
  • createContext 를 실행하면 Provider와 Consumer을 담고 있는 컨텍스트 객체가 생성
  • Provider는 state나 action.type에 따른 dispatch 함수들을 value prop에 넣어서 제공하는 역할
  • Consumer는 Provider에 담긴 state와 dispatch 함수들을 필요한 컴포넌트에서 접근할 수 있게 만드는 역할
//AddBtnModal.js

//createContext 생성(store 같은 역할)
import React, {createContext} from 'react';

export const myContext = createContext();

//  useContext를 통해 context.Consumer을 사용하지 않고 
// 간단히 컨텍스트에 접근가능
export const useMyContext = () => {
    return useContext(myContext)
}
  
//Provider 생성(dispatch함수들을 value prop에 넣어서 제공하는 역할)
export const ModalAddOpen = ({ children }) => {
    const [btnOpen, setBtnOpen] = React.useState(false);
    const btnClickOff = () => setBtnOpen(false);
    const btnClickOn = () => setBtnOpen(!btnOpen);
    const value = {
        btnOpen,
        btnClickOff,
        btnClickOn
    };

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

App.js에 Provider로 감싸준다 <ModalAddOpen>로 감싸주기

...import 생략
import { ModalAddOpen } from './Redux/modules/AddBtnModal'

function App() {
  return (
    <ModalAddOpen>
      <div className="App">
        <Header  />
      
        <Routes>
          <Route path='/' element={<Home />}></Route>
          <Route path='/user/detail' element={<DetailPage/>}></Route>
          <Route path='/login' element={<Login/>}></Route>
          <Route path='/register' element={<Register/>}></Route>
          <Route path='/user/:username' element={<UserPage/>}></Route>
        </Routes>
      
      </div>
    </ModalAddOpen>
  );
}

export default App;

모달창이 클릭되는 Header.jsx
useMyContext를 import하고 상수로 선언하기,
그렇다면 원하는 곳에 onClick 하여 적용할 수 있다.
선언된 상수로 함수를 호출해준다 myContext.btnClickOn

import { useMyContext } from '../Redux/modules/AddBtnModal';

const Header = () => {
  const myContext = useMyContext();

  return (
    <>
      <GlobalStyle />
      <HeaderContainer>
        <HeaderInner>
    
          <HeaderContentSize style={{ cursor: 'pointer' }} onClick={() => { navigate('/') }}>
            Instargram
          </HeaderContentSize>

          <div>
            <img onClick={myContext.btnClickOn} alt="add" src={add}></img>
          </div>

        </HeaderInner>
      </HeaderContainer>
    </>
  )
}

모달창 열기 구현 Home.jsx

import { useMyContext } from '../../Redux/modules/AddBtnModal'

const Home = () => {
  const myContext = useMyContext();
  
  const ClickOuter = () => {
    //외부 클릭시 모달창 닫기 구현
    myContext.btnClickOff();
  }
  return (
    <div>
      <HomeContainer>
      //boolean 값으로 모달창 열고 닫기
        {myContext.btnOpen ? <AddButton /> : null}
        <HomeInner onClick={ClickOuter}>
          <Main  />
        </HomeInner>
      </HomeContainer>

    </div>
  )
}

redux와 context의 차이는?

-redux: 하나의 스테이트 소스 트리에서 상태를 관리한다.
-context: 스테이트 소스에 대한 제한이 없다.

즉 어떤 단위에서만 공유하면 되는 정보를 굳이 redux를 통해서 전역적으로 관리할 필요는 없기 때문입니다. 주로 ui적 요소(모달창 on/off 상황, 테이블 필터 쿼리 상황 등등..)를 공유하는데 사용됩니다.

출처: 위의 블로그와 동일 (https://leedr0730.medium.com/react-context-api%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-5d2f95d67b09)

profile
winwin
post-custom-banner

0개의 댓글