はじめに
私自身プログラミングでわからないことがあった時は、ドキュメントやいろんな方が書いた記事を読んで問題を解決しています。その際に、解決できた記事についてはブックマークをして保存するようにしてます。ですが、ブックマーク一覧を探すのに手間がかかっていて「探すのめんどくさいな😅」と感じるようになり、ブログ内にブックマークした一覧を表示できる機能があればいいと考えました。
サンプルではありますが、私が考えたブックマーク機能がこちらです。
全体のコード
はじめに全体のコードを確認していきましょう。
今回はコンポーネントはなしで記述してます。
import type { NextPage } from 'next';
import Image from 'next/image';
import React, { useState } from 'react';
import Profile from '~/img/profile.png';
interface CardProps {
title: string;
text: string;
image: {
src: StaticImageData;
width: number;
height: number;
alt: string;
};
bookmark: boolean;
}
const Home: NextPage = () => {
const dataList: CardProps[] = [
{
title: 'Title1',
text: 'テキストテキストテキストテキストテキストテキストテキスト',
image: {
src: Profile,
width: 300,
height: 200,
alt: '',
},
bookmark: false,
},
{
title: 'Title2',
text: 'テキストテキストテキストテキストテキストテキストテキスト',
image: {
src: Profile,
width: 300,
height: 200,
alt: '',
},
bookmark: false,
},
{
title: 'Title3',
text: 'テキストテキストテキストテキストテキストテキストテキスト',
image: {
src: Profile,
width: 300,
height: 200,
alt: '',
},
bookmark: false,
},
];
const [cardList, setCardList] = useState(dataList);
return (
<div className='flex'>
<div className=' grid grid-cols-2 w-2/3'>
{cardList.map((data, i) => {
return (
<div
key={i}
className='mt-8 w-[300px] rounded-lg border border-gray-300 shadow-lg hover:opacity-70 transition duration-500 hover:-translate-y-4'
>
<Image
src={data.image.src}
width={data.image.width}
height={data.image.height}
alt={data.image.alt}
className='rounded-t-lg'
/>
<h3 className='mt-2 text-3xl font-semibold tracking-[2px]'>{data.title}</h3>
<p className='px-3 my-2 text-left'>{data.text}</p>
<p className='pb-4 mr-4 text-right'>
{data.bookmark === true ? (
<span
className='text-3xl text-left text-yellow-400 cursor-pointer select-none'
onClick={() => {
data.bookmark = false;
setCardList([...cardList]);
}}
>
★
</span>
) : (
<span
onClick={() => {
data.bookmark = true;
setCardList([...cardList]);
}}
className='text-3xl cursor-pointer select-none'
>
☆
</span>
)}
</p>
</div>
);
})}
</div>
<div className='mt-8'>
<h2 className='text-3xl font-bold'>Bookmark List</h2>
<div className='overflow-auto h-[500px]'>
{cardList.map((data, i) => {
if (data.bookmark === true) {
return (
<div
key={i}
className='mt-4 w-[300px] rounded-lg border border-gray-300 shadow-lg hover:opacity-70'
>
<Image
src={data.image.src}
width={data.image.width}
height={data.image.height}
alt={data.image.alt}
className='rounded-t-lg'
/>
<h3 className='mt-2 text-3xl font-semibold tracking-[2px]'>{data.title}</h3>
<p className='px-3 my-2 text-left'>{data.text}</p>
<p className='pb-4 mr-4 text-right'>
{data.bookmark === true ? (
<span
className='text-3xl text-left text-yellow-400 cursor-pointer select-none'
onClick={() => {
data.bookmark = false;
setCardList([...cardList]);
}}
>
★
</span>
) : (
<span
onClick={() => {
data.bookmark = true;
setCardList([...cardList]);
}}
className='text-3xl cursor-pointer select-none'
>
☆
</span>
)}
</p>
</div>
);
}
})}
</div>
</div>
</div>
);
};
export default Home;
useStateでブックマークの状態を管理する
ブックマークを管理するのはReack Hooks のuseState を使います。ノートに書いた内容だとこんな感じをイメージしました。
ブックマークに登録する箇所のonClickで状態管理をしていきます。クリックされた箇所だけをfalseからtrue と trueからfalse に変更してカードリストの変数を更新するので、onClickでこのように記述していきます。
{cardList.map((data, i) => {
if (data.bookmark === true) {
return (
<div
key={i}
className='mt-4 w-[300px] rounded-lg border border-gray-300 shadow-lg hover:opacity-70'
>
<Image
src={data.image.src}
width={data.image.width}
height={data.image.height}
alt={data.image.alt}
className='rounded-t-lg'
/>
<h3 className='mt-2 text-3xl font-semibold tracking-[2px]'>{data.title}</h3>
<p className='px-3 my-2 text-left'>{data.text}</p>
<p className='pb-4 mr-4 text-right'>
{data.bookmark === true ? (
<span
className='text-3xl text-left text-yellow-400 cursor-pointer select-none'
onClick={() => { ← // ここで設定
data.bookmark = false;
setCardList([...cardList]);
}}
>
★
</span>
) : (
<span
onClick={() => { ← // ここで設定
data.bookmark = true;
setCardList([...cardList]);
}}
className='text-3xl cursor-pointer select-none'
>
☆
</span>
)}
</p>
</div>
);
}
})}
最後に、ブックマークのエリア内にtrueの時はカードリストの変数が表示されるように記述をしてきます。
<div className='overflow-auto h-[500px]'>
{cardList.map((data, i) => {
if (data.bookmark === true) {
return (
<div
key={i}
className='mt-4 w-[300px] rounded-lg border border-gray-300 shadow-lg hover:opacity-70'
>
<Image
src={data.image.src}
width={data.image.width}
height={data.image.height}
alt={data.image.alt}
className='rounded-t-lg'
/>
<h3 className='mt-2 text-3xl font-semibold tracking-[2px]'>{data.title}</h3>
<p className='px-3 my-2 text-left'>{data.text}</p>
<p className='pb-4 mr-4 text-right'>
{data.bookmark === true ? (
<span
className='text-3xl text-left text-yellow-400 cursor-pointer select-none'
onClick={() => {
data.bookmark = false;
setCardList([...cardList]);
}}
>
★
</span>
) : (
<span
onClick={() => {
data.bookmark = true;
setCardList([...cardList]);
}}
className='text-3xl cursor-pointer select-none'
>
☆
</span>
)}
</p>
</div>
);
}
})}
</div>
最後に
リロードした時などはブックマークの記録は消えてしまうので、データベースやローカルストレージなどに保存をしておかなければブックマークの情報は初期状態に戻るのでその辺りはご自身の好きな方法で保存を検討してみてください!
最後までお読みいただきありがとうございます。