[nextjs] title 적용 / hoc 패턴활용하기

HYEJIN·2022년 12월 8일
0

프로젝트 기록

목록 보기
2/6
post-custom-banner

< 1번째 시도 >


이렇게 할 경우, 일일히 페이지에서 html에 Seo컴포넌트를 추가하고 props로 title을 넣어줘야한다.
이에 대해서 묶어서 어떻게 해결할 수 있을까 ?

<2번째 시도>

SSR
getServerSideProps함수 > pageProps에다가 넘겨준다.
적용해보니 SEO 컴포넌트에 일일히 props를 넘겨주는것과 크게 다르지 않게 느껴졌다.

// components/Seo.ts
import Head from "next/head";

export type SeoPageProps = {
  pageTitle: string;
  pageDesc: string;
};

export default function Seo({ pageTitle, pageDesc }: SeoPageProps) {
  return (
    <Head>
      <title>{pageTitle} | Hi Five</title>
      <meta property="og:title" content={pageTitle ? pageTitle : "우쥬"} key="ogtitle" />
      <meta property="og:description" content={pageDesc ? pageDesc : "교환일기 | 일정관리 "} key="ogdesc" />
    </Head>
  );
}
// pages/_app.tsx
export default function App({ Component, pageProps }: AppProps<SeoPageProps>) {
  const [isLightTheme, setIsLightTheme] = useState(true);
  const { pageTitle, pageDesc } = pageProps;
  console.log(pageTitle, pageDesc);

  return (
    <ThemeProvider theme={isLightTheme ? lightTheme : darkTheme}>
      <GlobalStyle />
      <Layout>
        <Seo pageTitle={pageTitle} pageDesc={pageDesc}></Seo>
        <Component {...pageProps} />
      </Layout>
    </ThemeProvider>
  );
}
//pages/login.tsx

//...일부 생략 

export default function login() {
  return {
   <></> 
  }
}
export async function getServerSideProps() {
  return {
    props: {
      pageTitle: "로그인",
      pageDesc: "우쥬 로그인 페이지 입니다.",
    },
  };
}

<hoc 패턴>

hoc패턴 >컴포넌트에서 컴포넌트를 호출한다.
페이지 안에 있는 getServerSideProps를 호출 할 때 WithGetServerSideProps 내에 커스톰된 getServerSideProps가 호출된다.
ssr에서 context 이용

context.resolvedUrl > 현재 url을 가져올 수 있어서 ,
그 경로일 경우 어떤 title이 올 지 정해주게되면
일일히 props로 넘기지 않아도 url path에 따라서 titl을 지정할 수 있게 된다.

//hocs/withGetServerSideProps.ts
import { GetServerSideProps, GetServerSidePropsContext } from "next";

const PATH = {
  HOME: "/",
  LOGIN: "/login",
  JOIN: "/join",
};

const mapPathToTitle: { [key: string]: string } = {
  [PATH.HOME]: "홈",
  [PATH.LOGIN]: "로그인",
  [PATH.JOIN]: "회원가입",

};

const mapPathToDesc: { [key: string]: string } = {
  [PATH.HOME]: "홈 화면 입니다. ",
  [PATH.LOGIN]: "우쥬, 로그인 페이지 입니다. ",
  [PATH.JOIN]: "회원가입 페이지 입니다.",
};

const withGetServerSideProps = (getServerSideProps: GetServerSideProps) => {
  console.log("withGetServerSideProps");
  return async (context: GetServerSidePropsContext) => {
    const pagePath = context.resolvedUrl;
    return await getServerSideProps(context).then((res: { [key: string]: any }) => {
      console.log(res.props);
      return {
        ...res,
        props: {
          ...res.props,
          isError: false,
          pageTitle: mapPathToTitle[pagePath],
          pageDesc: mapPathToDesc[pagePath],
        },
      };
    });
  };
};

export default withGetServerSideProps;

실제로 페이지 내에서 사용할 때 아래와 같이 사용하였다.
페이지별로 데이터를 패치하거나 해야할 때는 아래코드 내에서 작업해주면 된다.

export const getServerSideProps = withGetServerSideProps(async (context: GetServerSidePropsContext) => {
  return {
    props: {},
  };
});
post-custom-banner

0개의 댓글