고차 함수가 함수를 받고 함수를 반환하듯
컴포넌트를 받고 컴포넌트를 반환하는 고차 함수
React.memo() 가 대표적인 고차 컴포넌트다
컴포넌트 자체의 로직을 재사용한다
with 로 시작하는 네이밍을 하고
컴포넌트 전체를 감싼다는 점에서 영향력이 크다
자주 쓰면 복잡성이 증대함
로그인 상태에 따라 다른 컴포넌트를 반환하는 고차 컴포넌트
import React, { ComponentType } from "react";
import { JSX } from "react/jsx-runtime";
import IntrinsicAttributes = JSX.IntrinsicAttributes;
import Intro from "@app/intro/page";
// 로그인 상태에 따라 컴포넌트를 렌더링
interface Props {
isLoggedIn: boolean;
}
export function withLogin<T>(
Component: ComponentType<Omit<IntrinsicAttributes & T & Props, "isLoggedIn">>,
) {
return function (props: IntrinsicAttributes & T & Props) {
const { isLoggedIn, ...restProps } = props;
if (!isLoggedIn) return <Intro />;
return <Component {...restProps} />;
};
}
사용
"use client";
import { useEffect, useState } from "react";
import Admin from "@app/admin/page";
import { withLogin } from "../utils/with-login";
function Page() {
const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);
useEffect(() => {
const token = sessionStorage.getItem("token");
setIsLoggedIn(!!token);
}, []);
return <Admin />;
}
export default withLogin(Page);
타입은 아직도 어렵다..
import { JSX } from "react/jsx-runtime";
import IntrinsicAttributes = JSX.IntrinsicAttributes;
import { Theme } from "@components/providers/theme-provider";
interface Props {
theme: Theme | null;
}
function withTheme<T>(Component: ({ theme }: Props) => React.JSX.Element) {
return function themeComponent(props: IntrinsicAttributes & T & Props) {
const { theme, ...restProps } = props;
if (!theme) return <>loading...</>;
return <Component theme={theme} {...restProps} />;
};
}
export default withTheme;
이런식으로 타입을 정의할 수도 있다..
서로 다른 컴포넌트 내부에서 같은 로직을 공유하고자 할 때 사용
use 로 시작하는 네이밍
useEffect, useState와 같이 훅으로만 공통 로직을 격리할 수 있다면 사용자 정의 훅을 사용하는 것이 좋다
렌더링 결과물에도 영향을 미치는 공통 로직이라면 고차 컴포넌트를 사용