다이나믹 라우팅으로 상세페이지 보기

개발공부·2023년 1월 18일
0

* 결과

1) 상세페이지 보기 1(이미지가 있는 경우)

2) 상세페이지 보기 2(글만 있는 경우)

3) 상세페이지 보기 3(글만 있는 경우)

* 오류

1) localhost:3000/post/1로 넘어갈 때 이 프로젝트에서 사용하는 공공데이터 api 페이지(이하 오류 페이지)로 화면이 넘어감

-> 다른 예시로 localhost:3000/default나 localhost:3000/random (pages에 없는 라우팅 주소)로 입력해도 오류 페이지로 넘어감
-> next rewrite()

next.config.js에서 rewrite()를 사용함

▶ front에서 공공데이터 api의 cors 문제를 해결하기 위해 사용했던 것을 backend쪽에서 해결 후 잊고 있었음
▶ 수정하니 정상 동작함

const nextConfig = {
  reactStrictMode: true,
  // async rewrites() { -> 해당 부분 삭제
  //   return [
  //     {
  //       source: "/:path*",
  //       destination: `https://krdict.korean.go.kr/api/search/:path*`,
  //     },
  //   ];
  // },
};

module.exports = nextConfig;

2) 오류 => title 관련

Hydration failed because the initial UI does not match what was rendered on the server.

▶ 검색엔진을 위해 title, meta 부분을 넣었는데 오류 발생
해결에 도움을 준 블로그

import Head from "next/head"; 추가

[수정 전 - pages/post/[id].js]

const Post = () => {

  return (
    <NavbarForm>
      <head>
        <title>{`title ${singlePost.User.nickname}님의 글`}</title>
        <meta name="description" content={`${singlePost.content}`} />
        <meta
          property="og:title"
          content={`${singlePost.User.nickname}님의 게시글`}
        />
        <meta property="og:description" content={singlePost.content} />
        <meta
          property="og:image"
          content={
            singlePost.Images[0]
              ? singlePost.Images[0].src
              : "https://engword.shop/favicon.ico"
          }
        />
        <meta property="og:url" content={`https://engword.shop/post/${id}`} />
      </head>
      <PostCard post={singlePost} />
    </NavbarForm>
  );
};

export default Post;

[수정 후 - pages/post/[id].js]

import axios from "axios";
import Head from "next/head";


const Post = () => {
  return (
    <NavbarForm>
      <Head>
        <title>{`title ${singlePost.User.nickname}님의 글`}</title>
        <meta name="description" content={`${singlePost.content}`} />
        <meta
          property="og:title"
          content={`${singlePost.User.nickname}님의 게시글`}
        />
        <meta property="og:description" content={singlePost.content} />
        <meta
          property="og:image"
          content={
            singlePost.Images[0]
              ? singlePost.Images[0].src
              : "https://engword.shop/favicon.ico"
          }
        />
        <meta property="og:url" content={`https://engword.shop/post/${id}`} />
      </Head>
      <PostCard post={singlePost} />
    </NavbarForm>
  );
};

export default Post;

* 코드

1) 기존 pages/post.js에서 pages/post/index.js 와 pages/post/[id].js로 분리

▶ 게시글 값 입력 시 상세페이지로 이동

const onPostDetail = useCallback(() => {
router.push(/post/${post.id});
}, []);

[pages/post/[id].js]

import axios from "axios";
import Head from "next/head";
import { useRouter } from "next/router";
import { useCallback } from "react";
import { useSelector } from "react-redux";
import { END } from "redux-saga";

import NavbarForm from "../../components/NavbarForm";
import PostCard from "../../components/post/PostCard";
import { loadPostRequest } from "../../redux/feature/postSlice";
import { loadMyInfoRequest } from "../../redux/feature/userSlice";
import wrapper from "../../redux/store";

const Post = () => {
  const router = useRouter();
  const { id } = router.query;
  const { singlePost } = useSelector((state) => state.post);

  const onGoSNS = useCallback(() => {
    router.push("/post");
  }, []);

  return (
    <NavbarForm>
      <Head>
        <title>{`title ${singlePost?.User.nickname}님의 글`}</title>
        <meta name="description" content={`${singlePost?.content}`} />
        <meta
          property="og:title"
          content={`${singlePost?.User.nickname}님의 게시글`}
        />
        <meta property="og:description" content={singlePost?.content} />
        <meta
          property="og:image"
          content={
            singlePost?.Images[0]
              ? singlePost?.Images[0].src
              : "https://engword.shop/favicon.ico"
          }
        />
        <meta property="og:url" content={`https://engword.shop/post/${id}`} />
      </Head>

      <div className="h-full mt-5">
        <div className="grid grid-cols-4 gap-6">
          <div className="col-span-1"></div>
          <div className="col-span-2">
            <div className="flex justify-center">
              <button
                onClick={onGoSNS}
                className="px-3 py-2 font-medium rounded-lg bg-light-green text-white hover:bg-light-beige hover:text-black"
              >
                게시글로 돌아가기
              </button>
            </div>
            <PostCard post={singlePost} />
          </div>
          <div className="col-span-1"></div>
        </div>
      </div>
    </NavbarForm>
  );
};

export const getServerSideProps = wrapper.getServerSideProps(
  async (context) => {
    const cookie = context.req ? context.req.headers.cookie : "";
    axios.defaults.headers.Cookie = "";
    if (context.req && cookie) {
      axios.defaults.headers.Cookie = cookie;
    }

    context.store.dispatch(loadMyInfoRequest());
    context.store.dispatch(loadPostRequest(context.params.id)); //단일 게시글 불러올 것
    context.store.dispatch(END);
    await context.store.sagaTask.toPromise();
  }
);

export default Post;
profile
개발 블로그, 티스토리(https://ba-gotocode131.tistory.com/)로 갈아탐

0개의 댓글