こんにちは。
Reactの開発で、「もっと見る」ボタンを押すと追加のカードアイテムが表示されるようなUIを作成したいケースがありました。
WebサイトのようにReactを使わないタイプの実装の場合、
- もっと見るボタンの押下時にJavaScriptの
classList.add
でクラスを付与し、is-active
クラスが付与された時の挙動をCSSで指定する
といった方法を取ることができます。
しかしReactではclassの付与という方法は現実的でないため実装に詰まってしまったため、備忘録も含めて解決法を書いていこうと思います。
実装方法
表示させたいカードレイアウトの件数をslice関数
を使って制御し、ボタン押下時にuseState
でslice関数の第二引数を変更することで「もっと見る」の挙動を再現することができる。
// 最初に表示させたい要素数をuseStateで定義
const [showNum, setShowNum] = useState(3);
// カードアイテムで表示させたいデータの取得用定数。ここでは
// dataをfetchする処理はここでは省略
const [data, setData] = useState([]);
const onClickButton = () => {
setShowNum(data.length);
};
return(
<>
<div className="grid grid-cols-3 gap-4">
{data.slice(0, showNum).map((elem) => {
return (
<a href={elem.url}>
<figure>
<img src="/assets/img/sample.jpg" />
</figure>
<div>
<h2>{elem.title}</h2>
</div>
</a>
);
})}
</div>
<button onClick={onClickButton}>
もっと見る
</button>
</>
);
何をしているか
JavaScriptのslice関数について
(配列名).slice(x, y)
とすることで、(配列名)の配列のインデックス番号x番目からy番目の直前の要素を抽出することができる。
これを配列のmapメソッドの前に置くことで、与えられた配列のうち特定の順番の要素だけをmapメソッドの対象にすることが可能。
// 予めslice関数で何件表示させたいかをuseStateの定数で決めておく
const [showNum, setShowNum] = useState(4);
{data.slice(0, showNum).map((elem) => {
// ここにmapメソッド内部の処理が入ります
})}
ボタン押下時の操作
「もっと見る」ボタンを押下した際にonclick
でshowNum
の値をdata.length
とすることでdata配列内に含まれるデータ全てがsliceの対象になる。
結果として「もっと見る」ボタン押下時に配列内のすべてのデータがmapメソッドで繰り返し処理されるためすべてのカードアイテムを表示することができる。
最後に
JavaScriptに慣れていないとmapメソッドの前に別の関数を使えることは盲点かもしれません(少なくとも私はそうでした)。
もっと見る型のUIはよく使われるUIなので実装の際の参考になれば幸いです。
参考資料