10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

watnow Advent Calendar 2024

Day 2

Next.js、muiを用いたページネーション

Posted at

こんにちは!watnowの神宮です。
今回はmuiを用いたページネーションについて書かせてもらいます!
DBはsupbaseを使っています!
いくつか問題点はある実装だと思いますが、読んでもらえれば幸いです!

1.MUIをインストールする。

npm install @mui/material @emotion/react @emotion/styled

2.Pagenationをとりあえずつくる

pags.tsx
"use client";
import Pagination from '@mui/material/Pagination';


const Pagenation: React.FC = ()=>{
    
    return(
        <Pagenation />   
    );

};
default export Pagenation

こんな感じのやつが表示される
スクリーンショット 2024-12-02 15.35.57.png

3.paginationをカスタマイズ

page.tsx
"use client";
import Pagination from '@mui/material/Pagination';

const Pagenation: React.FC = () =>{
    return (
        <Pagenation
            count={8} //表示されるページ数が8になる
            renderItem={(item)=>(   //ページネーションの両サイドにある<,>を矢印に
                <PaginationItem
                    {...item}
                    slots = {{
                        previous:()=> <div></div>,
                        next: ()=> <div></div>,
                    }}
                />
            )}
        />
    );
};
default export Pagenation

count
→ページネーションの総ページ数を決める

renderItem
→各ページアイテムをどのように表示するかを決める関数を
受け取って表示。

※各ページアイテムは以下の写真参照
スクリーンショット 2024-12-02 16.33.05.png

item
→各ページアイテムの情報を持っているオブジェクト

PaginationItem
→ページアイテムを表すコンポーネント

{...item}
→itemオブジェクトが持つプロパティをPagenationItemに渡している。

slots
→下記の~~~の部分を変えることで,ページネーションにある両端のボタンを変えることができる。

page.tsx
slots={{
    previoust:()=>  ~~
    next: ()=> ~~~
}}

4.ページごとに表示されるものを変える。

ここからの僕の実装は問題ありです。
とりあえず実装したいんだ!という方の参考になれば幸いです!

まず、流れを説明します。

useStateで現在のページ数、画面に表示したいもののデータを保持

ページネーションがクリックされたらページ数を+1

ページ数が変わったら、データをDBから取ってきて、画面に表示したいもののデータを更新。

必要なstateを用意する

page.tsx
const [services, setServices] = useState<Service[]>([]); //表示したもののデータ
const [pageNum,setPageNum] = useState(1); //現在のページ数
const [totalPageNum,setTotalPageNum] = useState(0); //総ページ数

ページネーションがクリックされた時の処理を用意する

pagaNumを次に進めます!!

page.tsx
    const scrollTop =()=>{
        window.scrollTo({ top:0 });
    };
  
    const handlePageChange =(_: React.ChangeEvent<unknown>, nextPage:number)=>{
        setPageNum(nextPage);
        scrollTop();
        console.log(nextPage);
      }
    return (
         <Pagenation
             //省略
                onChange=(handlePage)
            //省略
        />
    );

_
→このアンダースコアは変数名。Js,Tsで使わない変数を_で表す

React.cahnageEvent
→ReactのChangeイベントを表す

unknow
→unknowはどのhtml要素から発生したのかわからない時に使う。

scrollTop()
→ページネーションをクリックしたときにページ上部へ移動するため。

page.tsx
_: React.ChangeEvent<unknown>, 

nexPage: Paginationコンポーンネント勝手に計算して、次に表示するページを渡してくれます!

現在のpage数が変わった際の処理を用意

pageNumが変わったときに、ページ数に応じてデータを取得。

page.tsx
useEffect(()=>{
    const start = (pageNum-1) * servicesPerPage;
    const end = start + servicesPerPage - 1;

    const fetchService = async () => { //ページ数に応じてデータを取得
      const { data, error } = await supabase
        .from("services")
        .select("id,name,image")
        .order("id", { ascending: true })
        .range(start,end)
      if (error) {
        console.error("Error fetching events:", error);
      } else {
        console.log("Fetched data:", data);
        setServices((data as Service[]) || []);
      }
      setLoading(false);
    };

    fetchService()
  },[page])

start, end
→DBから取ってくるデータの最初の範囲を選ぶ。

.order("id", { ascending: true })
→idを使って昇順で取得

初回レンダリング時に表示されるデータ、ページに表示したいデータの総数を取得

page.tsx
useEffect(() => {
    const start = (pageNum-1) * servicesPerPage;
    const end = start + servicesPerPage - 1;

    const fetchService = async () => {
      const { data, error } = await supabase
        .from("services")
        .select("id,name,image")
        .order("id", { ascending: true })
        .range(start,end);

      if (error) {
        console.error("Error fetching events:", error);
      } else {
        console.log("Fetched data:", data);
        setServices((data as Service[]) || []);
      }

    };


    const fetchEventCount = async () => {
      const { count, error:countError} = await supabase
        .from("services")
        .select('*',{count:'exact',head: true});
      console.log("カウントしている",count);
      
      if (countError) {
        console.error("Error fetching event count",countError)
        return;
      }
      setTotalServiceNum(count || 0);
    }

    fetchService();
    fetchEventCount();
  }, []);

最初の関数は同じものを2回書いています。よくないです!!

count:'exact'
→データ数を取得

head: true
→head:trueにすることでデータをとらずにデータ数のみ取得

5.ページネーションの表示ページ数を変える

page.tsx

      <Pagination
        className={styles.pageNation}
        count={Math.ceil(totalServicesCount / servicesPerPage)}
        onChange={handlePageChange}
        renderItem={(item) => (       
        
      />

Math.ceil
→jsのメソッドで小数点以下を切りあげる。

上記のコードで完成になります!!

最後に

次回ページネーションを作る機会があれば、よりスムーズに作れるようになったと思います。

このように一つずつ自分ができることを増やしていきたです。

ここまで読んでくださりありがとうございます。
アドバイスがあれば気軽におっしゃってください!!!

10
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?