인스타 클론코딩 때 많은 모달창들을 다 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를 통해서 전역적으로 관리할 필요는 없기 때문입니다. 주로 ui적 요소(모달창 on/off 상황, 테이블 필터 쿼리 상황 등등..)를 공유하는데 사용됩니다.
출처: 위의 블로그와 동일 (https://leedr0730.medium.com/react-context-api%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C-5d2f95d67b09)