Context API
props 드릴링을 막아준다. (= import 해와서 props 내려줄 필요가 없다)
최대한 상위에서 다 관리해주는 것이 좋다.
(리덕스와 다른 점은 리덕스는 promise 를 제공하지 않는다. 그래서 리덕스 사가를 써야 한다. 또한 리덕스는 모든걸 상위에서 관리하지만 Context API 는 위에서 관리하되, 너무 불필요하게 위까지 가지 않도록 한다고 한 것 같다.)
이전 게시물의 정리를 참고하면
해당 context 파일에서는 provider 를 반환한다.
이 provider 를 최상위 app.tsx 에 감싸주면 그 아래 컴포넌트에서는 provider 의 value 에 접근할 수 있게 된다.
// 해당 context 파일
interface ContextType {
state: State;
handleStateTrue(): void;
}
const Context = React.createContext({} as ContextType);
type AuthProviderPropType = { children: React.ReactNode };
export function AuthProvider(props: AuthProviderPropType) {
const { children } = props;
return (
<Context.Provider value={{ state, handleStateTrue }}>
{children}
</Context.Provider>
);
}
// App.tsx
import { AuthProvider } from "./contexts";
function App(){
return (
<AuthProvider>
<div className="App">
<Dashboard />
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
</AuthProvider>
);
}
이렇게 import 해서 provider 로 감싸줌
이제 하위 컴포넌트인 Dashboard 에서는 어떻게 value 를 쓰는지 알아보겠다.
아까 context 파일에서 한 줄 추가하는데
useContext 까지 export 시켜준다.
export const useAuth = () => React.useContext(Context);
참고로 여기에선 useAuth 이라는 커스텀 훅을 만들어주었다.
// Dashboard.tsx
import { useAuth } from "../contexts";
export function Dashboard() {
const { handleStateTrue } = useAuth();
return (
<div className="dashboard">
<button onClick={handleStateTrue}>Click</button>
</div>
);
}
reducer
reducer 는 state 를 받고 state 반환하는 단순한 함수 라고 생각하면 된다.
// reducer 파일
export interface State {
value: boolean;
}
export type Action = { type: "SET_TRUE" } | { type: "SET_FALSE" };
export function reducer(state: State, action: Action): State {
switch (action.type) {
case "SET_TRUE": {
return { ...state, value: true }
}
case "SET_FALSE": {
return { ...state, value: false }
}
}
그럼 이제 context 에 reducer 를 결합해보겠다.
다시 되짚어보면 reducer 는 state 를 받고 state 를 다시 반환하는 함수일 뿐이었다.
// context 파일
import { State, Action, reducer } from "./reducer"; // reducer 에서 import
interface ContextType {
state: State;
handleStateTrue(): void;
}
const Context = React.createContext({} as ContextType);
type AuthProviderPropType = { children: React.ReactNode };
export function AuthProvider(props: AuthProviderPropType) {
const { children } = props;
const [state, dispatch] = React.useReducer(reducer, { value: false });
const handleStateTrue = () => {
dispatch({ type: "SET_TRUE" });
};
return (
<Context.Provider value={{ state, handleStateTrue }}>
{children}
</Context.Provider>
);
}
export const useAuth = () => React.useContext(Context);
useReducer 의 첫번째 인자는 reducer, 두번째 인자는 초기값 이다.
state 는 우리가 앞으로 컴포넌트에서 사용 할 수 있는 상태,
dispatch 는 액션을 발생시키는 함수.
코드리뷰에서 받았는데 setState 변수를 넘겨주는거는 자식 컴포넌트에서 부모 컴포넌트를 건드리는 건 좋지 않기 때문에 핸들러로 넘겨주는 것이 좋다고 한다.
import { useAuth } from "../contexts";
import React from "react";
export function Dashboard() {
const { handleStateTrue } = useAuth();
return (
<div className="dashboard">
<button onClick={handleStateTrue}>Click</button>
</div>
);
}
'💎 React' 카테고리의 다른 글
react lazy (0) | 2022.03.31 |
---|---|
아폴로 클라이언트 (0) | 2022.03.25 |
React - reducer (0) | 2022.03.08 |
React - Context (0) | 2022.03.07 |
MakeStyle 이 뭘까 (0) | 2022.03.05 |