HoC 를 만드는 함수 만들기
이제 Context API 에 좀 익숙해졌지요? 한가지만 더 해봅시다. 우리가 Context 를 만들 때 마다 HoC 를 작성하는게 귀찮을 수도 있습니다. 또, 같은 Context 를 사용하지만 상황에 따라 다른 props 를 전달해줘야 할 때도 있을 것입니다. 그러한 상황에 도움을 줄 수 있는 함수를 새로 만들어보겠습니다.
src/lib/createUseConsumer.js
import React from 'react';
const createUseConsumer = (Consumer) => (mapContextToProps) => (WrappedComponent) => {
// mapContextToProps 가 없으면 그냥 context 를 그대로 props 에 전달
const defaultMapContextToProps = (context) => ({context});
function UseConsumer(props) {
return (
<Consumer>
{
context => {
// context에서 원하는 값 추출
const contextProps = (mapContextToProps || defaultMapContextToProps)(context);
return (
<WrappedComponent
{...contextProps}
{...props}
/>
);
}
}
</Consumer>
);
}
// displayName 설정
const displayName = WrappedComponent.displayName || WrappedComponent.name || 'component';
UseConsumer.displayName = `UseConsumer(${displayName})`;
return UseConsumer;
}
export default createUseConsumer;
그럼, another Context 파일을 다음과 같이 작성해줄 수 있습니다.
src/contexts/another.js
import React, { Component, createContext } from 'react';
import createUseConsumer from '../lib/createUseConsumer';
const Context = createContext();
const {
Provider,
Consumer: AnotherConsumer
} = Context;
class AnotherProvider extends Component {
state = {
number: 1,
}
actions = {
increment: () => {
this.setState(
({ number }) => ({ number: number + 1 })
);
}
}
render() {
const { state, actions } = this;
const value = { state, actions };
return (
<Provider value={value}>
{this.props.children}
</Provider>
);
}
}
const useAnother = createUseConsumer(AnotherConsumer);
export {
AnotherProvider,
AnotherConsumer,
useAnother
};
이제 useAnother 함수에서는 어떤 값을 props 에 넣어줄 지 정해주는 mapContextToProps 를 필요로 하니, Counter 컴포넌트도 조금 수정해주세요.
src/components/Counter.js
import React from 'react';
import { useAnother } from '../contexts/another';
const Counter = ({ number, increment}) => {
return (
<div>
<h1>{number}</h1>
<button onClick={increment}>더하기</button>
</div>
);
};
export default useAnother(
({ state, actions }) => ({
number: state.number,
increment: actions.increment
})
)(Counter);
코드를 저장하고, 기존의 카운터가 제대로 작동하는지 확인해보세요.