🚀Next.js + Tailwind.cssを使用してブログ-3を作成します.動的ルーティング実装ページの名前付けの使用

34772 ワード

リアクターによるページネーミングは,データのArrayをスライスし,現在のページネーミングを1増加させることで実現する.
Next.jsは動的ルーティングの利点を利用して,ページネーミングを動的に実施することを確保する

🚀 Dynamic Routing Pagination


まず、繰り返し使用するpostsデータを減算して関数としてエクスポートし続けます.
** ◼ posts data function export
//lib/posts.js
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import { sortByDate } from "utils";
export const getPosts=() => {
	const files= fs.readdirSync(path.join('posts'));
    const posts= files.map(file => {
    	const slug= file.replace('.md','');
        const markdownWithMeta= fs.readfileSync(path.join('posts'),file,'utf-8');
        const {data:frontmatter}= matter(file);
        return {frontmatter,slug};
    }) 
    return posts.sort(sortByDate);
}
◼ pagination markup+ css
export default function Pagination(){
	return <div className="mt-6">
    	<ul className="flex pl-0 list-none my-2">
        	<li className="relative block py-2 px-3 leading-tight bg-white border border-gray-300 text-gray-800 mr-1 hover:bg-gray-200 cursor-pointer">
              이전페이지
            </li>
	{..pagination Array.map()}
             <li className="relative block py-2 px-3 leading-tight bg-white border border-gray-300 text-gray-800 mr-1 hover:bg-gray-200 cursor-pointer">
              이전페이지
            </li>
        </ul>
    </div>
}
構成ディレクトリの作成(設定に必要な変数のエクスポート)
	//config/index.js
    export const POSTS_PER_PAGE= 6;
paginationの原理を振り返ると
  • 1. page/[page index]のパスを指定し、page/[page_index].jsファイルを作成します.
  • 2. [page_index].jsページでは、getStaticPathsとして事前に表示するパスのリストを定義します.
  • 2.1ページに入るパスの変数を、データ長全体に表示されるページに分割し、Mathに分割します.ceil()に上昇させます.
    const pageNumber= Math.ceil(data.length/3)
  • 2.2空の配列を作成し、for文をpushに回転し、params objを1-pageNumberに入れ、
    let paths= [];
    for(let i=1;i<=pageNumber;i++){
        paths.push({params:{page_index:i.toString()}})
    }
  • に戻します.
  • 3. 現在のparamsをgetStaticPropsにインポートして現在のページを取得し、Array.slice(startIdx,endIdx)にデータを切り取り、data, pageNumber, currentPageに戻ります.
  • 4. default関数は、受信したデータをpropsとしてPaginationに送信し、Pagination {currentPage,pageNumber} propsに送信する
  • 5. ページングで最初のページ/最後のページのページング矢印を非表示にし、ページ名をクリックするとurlパス
  • を変更します.

    1. pages/blog/page/[page_index].jsファイルの作成


    ダイナミックパスを使用してpage urlを変更する必要があるため、jsファイルを作成するためにパスを指定する必要があります.
    // pages/blog/page/[page_index].js
    export default function BlogPage(){
    	return     <Layout>
          <div className="flex justify-between">
            <div className="w-3/4 mr-10">
              <h1 className="text-4xl border-b-4 p-5">모든게시물 </h1>
              <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-5">
              	{Array.map()}
              </div>
            </div>
            <div className="w-1/4">
              {카테고리 만들 자리}
            </div>
          </div>
        </Layout>
    }

    2.getStaticPathsを使用してパスリストを指定する


    ◾ Pages/blog/page/[page_index].js
     import { getPosts } from "@/lib/posts";
     import { POSTS_PER_PAGE } from "config";
     export async function getStaticPaths(){
     	const posts= getPosts();
        //posts 데이터 가져옴
        const pageNumber= Math.ceil(posts.length / POSTS_PER_PAGE);
        //페이지 네이션의 페이지 갯수 구하기
        let paths=[];
        for(let i=1;i<=pageNumber;i++){
        	paths.push({params:{page_index:i.toString()}})
        }
        //빈 배열 만들어서 i 증감시켜서 return 시킬 params obj 배열 만들기
        return {paths,fallback:false}
     }

    3.getStaticPropsを使用して必要なpropsを返す

    export async function getStaticProps({params}){
    	const page= parsInt((params && params.page_index)||1);
        // blog/index.js에서 BlogPage function을 export default 시킬 꺼임. 그때의 url 의 params가 없기 때문에 params 가 없을 때는 1로 지정하는 조건문을 걸어줌.
    	const posts= getPosts();
        const pageNumber= Math.ceil(posts.length / POSTS_PER_PAGE);
        const startIndex= page-1;
        // 배열 index는 0으로 시작 하기 때문에
        const orderedPosts= posts.slice(startIndex * POSTS_PER_PAGE,(startIndex+1)* POSTS_PER_PAGE);
        // (처음 시작인덱스 * 보여질 아이템 수), (다음 인덱스 * 다음 보여질 아이템 수)로 배열 자르기
        return {
        	props:{
            	posts:orderedPosts,
                	currentPage:page,
                	pageNumber
            }
        }
    }

    4.BlogPageからアイテムを取得する

    export default function BlogPage({ posts, numPages, currentPage }) {
      return (
        <Layout>
          <div className="flex justify-between">
            <div className="w-3/4 mr-10">
              <h1 className="text-4xl border-b-4 p-5">모든게시물 </h1>
              <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-5">
                {posts.map((post, index) => (
                  <Post post={post} key={index} />
                ))}
              </div>
            </div>
            <div className="w-1/4"> 
            </div>
          </div>
        </Layout>
      );
    }
    ◾ blog/index.jsでのデフォルトblogPage export
    import BlogPage from "./page/[page_index]";
    export default BlogPage;
    これでexport、importなら

    ArremessagentㅜㅜgetStaticPropsはBlogPageのみをインポートしていないのでindex.js内で文章が見つからなかったのでundefinedになったので、愛楽男.getStaticProps度の輸入で、輸出が必要です.
    import { getStaticProps } from "./page/[page_index]";
    import BlogPage from "./page/[page_index]";
    export { getStaticProps };
    export default BlogPage;

    5.Pagination Componentの作成


    PaginationでcurrentPageとpageNumberを渡します.
    //pages/blog/page/[page_index].js
    export default function BlogPage({posts,pageNumber,currentPage}){
      {...생략}
      <Pagination currentPage={currentPage} pageNumber={pageNumber} />
    }
    ◾ Pagination.js Component
    import Link from "next/link";
    export default function Pagination({pageNumber,currentPage}){
    	const isFirst= currentPage === 1 ; //현재 페이지가 첫번쨰 페이지 인지 확인
        	const isLast= currentPage === pageNumber; //마지막 페이지 인지 확인
    	return (
              <div className="mt-6">
              <ul className="flex pl-0 list-none my-2">
                  {
                	!isFirst && <Link href={`/blog/page/${currentPage-1}`}>
                  <li className="relative block py-2 px-3 leading-tight bg-white border border-gray-300 text-gray-800 mr-1 hover:bg-gray-200 cursor-pointer">
                      이전페이지
                    </li>
                </Link>
                   }
                //첫번째 페이지가 아니라면 currentPage -1 시키면서 이전페이지로 url 변경
     	{
                Array.from({length:pageNumber},(_,index) => (
              <Link href={`/blog/page/${i + 1}`}>
                <li className="relative block py-2 px-3 leading-tight bg-white border border-gray-300 text-gray-800 mr-1 hover:bg-gray-200 cursor-pointer">
                  {i + 1}
                </li>
              </Link>
                ))
            }
            {!isLast && (
              <Link href={nextPage}>
                <li className="relative block py-2 px-3 leading-tight bg-white border border-gray-300 text-gray-800 mr-1 hover:bg-gray-200 cursor-pointer">
                  다음페이지
                </li>
              </Link>
            )}
             //마지막 페이지가 아니라면 currentPage +1 시키면서 다음 페이지로 url 변경
              </ul>
            </div>
        )
    }

    🗨 Array.from()

    Array.from(arrayLike[, mapFn[, thisArg]])Array.from()メソッドは、類似アレイオブジェクト(array-like object)または反復可能オブジェクト(iterable object)を浅くコピーすることによって、新しいArrayオブジェクトを作成します.

  • arrayLike
    アレイに変換する類似のアレイオブジェクトまたは重複可能なオブジェクト.

  • mapFnOptional
    配列内のすべての要素に呼び出すマッピング関数.

  • thisArgOptional
    mapfn実行時に使用する値.

  • Example
  • Array.from([1, 2, 3], x => x + x);
    // [2, 4, 6]
    Array.from({length: 5}, (v, i) => i);
    // [0, 1, 2, 3, 4]

    UnScoreからParameterへ

  • は、最初のパラメータが使用されていないことを示す.
  • 次の位置決めは類似の分類ルーティングです