고차 컴포넌트 예제
1. 커스텀 래퍼 컴포넌트
아래 return 되는 React 요소를 감싸주는 <MessageContext.Provider />
컴포넌트를 커스텀 컴포넌트로 만들 수 있다.
return (
<MessageContext.Provider
value={{
message: this.state.message,
changeMessage: this.changeMessage
}}
>
<Print>{this.state.message}</Print>
<GrandParent parentCount={2} childrenCount={2} />
</MessageContext.Provider>
);
아래와 같이 컴포넌트를 반환하는 함수를 만든다. 아래의 함수에서 props
는 <MessageContext.Provider />
의 value
와 children
을 받아오게 된다. 그렇기 때문에 props
를 받아오고 해당 props
를 번거롭게 다 지정해서 컴포넌트의 속성으로 구조 분해 할당하는 것이 아니라 나머지 매개 변수를 사용하면 간단하다.
// 컨텍스트의 Provider(공급자) 컴포넌트를 래퍼 컴포넌트로 내보내기
export const MessageProvider = props => {
return <MessageContext.Provider {...props} />;
};

1.2 Provider 래퍼 컴포넌트
Firebase 인증 예제에서 사용된 코드이다. value
의 객체 형태로 작성하지 않고 callback
함수 같은 경우엔 아래와 같이 useCallback()
훅을 사용해서 함수를 내보낼 수 있다.
const FirebaseAuthProvider = ({ children, ...restProps }) => {
const [state, dispatch] = React.useReducer(
firebaseAuthReducer,
initialAuthValue
)
const signUp = React.useCallback((email, password) => {
return auth
.createUserWithEmailAndPassword(email, password)
.then((response) => {
console.log(response.user)
console.log('회원가입 성공')
dispatch(signUpAction(response.user))
})
}, [])
const signIn = React.useCallback((email, password) => {
return auth.signInWithEmailAndPassword(email, password).then((response) => {
console.log(response.user)
console.log('로그인 성공')
dispatch(signInAction(response.user))
})
}, [])
const signOut = React.useCallback(() => {
return auth.signOut().then(() => {
console.log('로그아웃 성공')
dispatch(signOutAction())
})
}, [])
const value = { ...state, signUp, signIn, signOut }
return (
<FirebaseAuthContext.Provider value={value} {...restProps}>
{children}
</FirebaseAuthContext.Provider>
)
}
2. HOC → 일반 함수
먼저 생각하기, 고차 컴포넌트를 왜 사용할까?
context를 사용해서 자식 컴포넌트가 value를 받아오려면 Consumer 컴포넌트를 사용하거나 context Type을 사용해서 value를 받아와야 한다.
Cunsumer을 사용해서 value를 받아오는 것은 코드가 복잡해져 개인적으로 잘 사용하지 않게 된다.
그리고 (클래스 컴포넌트의) context Type을 사용해서 value를 받아오는 방식은 클래스 컴포넌트를 사용해야 한다는 제약이 있어서 번거롭다.
그래서 context Type 방식을 사용할 때 클래스 컴포넌트를 매번 사용해야 한다는 번거로움을 해결하기 위해 함수형 컴포넌트를 전달했을 때 context Type을 사용하는 클래스 컴포넌트가 반환되는 고차 컴포넌트를 만들어 사용한다.

2.2 컴포넌트 별칭 등록
displayName 속성을 사용해서 컴포넌트의 이름을 설정할 수 있다. 이렇게 설정하면 디버깅에 용이하다.
_withMessage.displayName = "whidMessage";

3. HOC → 커링 함수
4. 커스텀 훅(Hook)
속성 병합 이전에 배웠다 시피 속성의 이름이 같은 속성을 부모로 부터 전달 받으면 자식의 속성은 무시된다고 배웠다.
그 때, 나머지 연산자를 사용해서 병합하는 방법을 배웠다. 이번에는 따로 조건처리를 해서 오류가 나는 것을 방지하는 방법으로 사용해보자.

아래 handle이라는 변수에 context의 메서드와 부모 컴포넌트에서 받아온 onClick 속성을 병합했다. 이렇게되면 이전에 속성이 무시되지 않고 병합되어 정상 작동한다.
// Child Component
const handleClick = () => {
context?.changeMessage(message);
typeof onClick === "function" && onClick();
};
5. 재조정 주의하기
아래 처럼 defaultStyle을 컴포넌트 내부에 생성할 경우 재조정의 문제로 브라우저의 성능에 문제가 될 수 있다.

아래와 같이 컴포넌트 외부에 defaultStyle를 정의할 경우 전역이 오염된다.

가장 좋은 방법은 아래와 같이 네임스페이스를 사용해서 컴포넌트 외부에 객체를 정의 하는 방법이다.
이렇게 하면 전역을 오염시키지 않고 재조정 문제도 해결할 수 있어서 좋다.

6. props 검사하기
오타로 인해 속성과 context를 받아오질 못했다. 그래서 속성을 잘 받아 왔는지 확인하기 위해 props를 검사해 본다.
class에서 context는 기본적으로 object로 받아온다.
함수에서 context는 기본적으로 array로 받아온다.

7. 기억하기
매개 변수 안에서 구조 분해 할당
Last updated
Was this helpful?