2021. 7. 7. 17:29ㆍ프론트엔드/React.js
사실 나는 HOC를 활용한 컨텍스트만 사용했다.
왜냐면 그렇게 배워서...
그러다가 Hook 공식 문서를 읽어보고
'어? 그럼 Context도 Hook으로 할 수 있겠는데?'
생각을 해서 개발을 해보려는데
https://ko.reactjs.org/docs/hooks-reference.html#usecontext
useContext가 이미 있었다 ^___^
어후 안 읽어봤으면 또 개고생했을 뻔
HOC에 대해 알아보자
Context를 사용하는 방법은 다른 포스팅에서 알아보기로 하고,
HOC를 이용해서 컴포넌트를 Wrap하는 방법을 알아보자.
HOC는 Higher Order Component로, 말 그대로 상위 컴포넌트로 감싸는 방식이다.
예를 들어 이런 경우를 보자.
function App() {
return (
<div>
<A />
<B />
<C />
</div>
)
}
이런 A, B, C라는 컴포넌트가 있을 때, 이 컴포넌트를 어떤 컴포넌트의 자식으로 내리고 싶다.
예를 들면, 이전에 했던 NullWrapper를 생각해보자.
function App() {
return (
<div>
<NullWrapper>
<A />
</NullWrapper>
<NullWrapper>
<B />
</NullWrapper>
<NullWrapper>
<C />
</NullWrapper>
);
}
너무 지저분하다..
아무튼 저렇게 다른 컴포넌트에 Wrap을 하게 되면, 코드를 보기도 힘들게 되고, 노가다도 심해진다.
그래서 감싸는 코드를 만드는 것이다.
function withNullWrapper(Component) {
return (
<NullWrapper>
<Component />
</NullWrapper>
)
}
function App() {
return (
<div>
{withNullWrapper(A)}
{withNullWrapper(B)}
{withNullWrapper(C)}
</div>
);
}
하지만 이것도 좀 보기 그럴 수 있다.
A라는 컴포넌트는 어디에서 사용되던지 NullWrapper에 감싸져야한다면,
매번 사용할때마다 withNullWrapper를 호출해야 한다.
그렇다면 A 자체를 Wrap하면 어떨까?
function withWrapper(Component) {
return (
<div style={{ backgroundColor: 'rgb(125,125,125)' }}>
<Component />
</div>
)
}
function A() {
return (
withWrapper(() =><div>A 입니다</div>)
)
}
function App() {
return (
<div>
<A />
</div>
);
}
와! 너무너무 깔끔해요 ^____^
부모님 코드에 꼭 놔드려야겠어요~
여기서 한술 더 떠서 Component를 Wrap해서 export할 수도 있다.
fucntion A() {
return (
<>A 입니다</>
);
}
export default withNullWrapper(A);
이러면 A 내부에 NullWrapper로 감싸지 않아도 다른 곳에서 사용할 때 자동으로 Wrap된다.
HOC를 이용한 Context 활용법
이 HOC를 이용해서 Context를 활용해보자.
// SurveyContext.tsx
const SurveyContext = React.createContext({});
function withSurveyContext(WrappedComponent: WrappedType) {
return (props: any) => (
<SurveyContext.Consumer>
{obj => (obj
? <WrappedComponent {...obj} {...props} />
: <div />
)}
</SurveyContext.Consumer>
)
};
export default SurveyContext
export { withSurveyContext }
// App.tsx
function App() {
return (
<SurveyContext.Provider value={{ weight: 0 }}>
<A />
</SurveyContext.Provider>
)
}
// A.tsx
function A(props) {
const { weight } = props;
return (
<div>{weight}</div>
);
}
export default withSurveyContext(A);
세개의 파일로 나눠봤다.
App.js나 index.js (컴포넌트 트리 최상위)에 Provider로 감싸주는걸 잊지 말고,
Context.Consumer를 Wrap하는 withSurveyContext를 export해준다.
그러면 이제 withSurveyContext에 감싸진 컴포넌트는,
<SurveyContext.Consumer>에 감싸진 효과를 얻게 된다.
최종 트리는 다음과 같다.
<SurveyContext.Provider value={{ weight: 0 }}>
<SurveyContext.Consumer>
{({ weight }) => <div>{weight}</div>}
</SurveyContext.Consumer>
</SurveyContext.Provider>
Hook (useContext)를 이용해보자.
우선 useContext의 인자는 Context 그 자체다. Provider나 Consumer를 전달하지 않도록 조심하자.
const SurveyContext = React.createContext({});
...
const survey = useContext(SurveyContext);
이렇게 되면, Context.Provider에 전달된 value를 사용할 수 있다.
이 방법을 사용해서 위의 예제를 바꿔보자.
// SurveyContext.tsx
const SurveyContext = React.createContext({});
export default SurveyContext
// App.tsx
function App() {
return (
<SurveyContext.Provider value={{ weight: 0 }}>
<A />
</SurveyContext.Provider>
)
}
// A.tsx
function A() {
const survey = useContext(SurveyContext);
const { weight } = survey;
return (
<div>{weight}</div>
);
}
export default A;
... 뭐 그렇다. 끝났다.
참고 자료
'프론트엔드 > React.js' 카테고리의 다른 글
React에서 배경을 깔쌈하게 넣어보자 (0) | 2021.07.12 |
---|---|
Javascript for 반복문 정리 (0) | 2021.07.09 |
React Router 배워보기 (0) | 2021.07.04 |
Material-UI Theme에 대해 알아보자 (0) | 2021.07.03 |
React Hook에 대한 탐구 (0) | 2021.07.03 |