【React】Reactでボタンをクリックすると、内容が表示されるアコーディオンを実装する
React

【React】Reactでボタンをクリックすると、内容が表示されるアコーディオンを実装する

作成日:2022年06月30日
更新日:2022年06月30日

React でボタンをクリックすると、内容が表示されるアコーディオンを実装します。

まずは、アコーディオンで表示するタイトルと内容を配列で作成します。

jsx
import React from "react";
function App() {
const menus = [
{ title: "6月30日", content: "晴れ" },
{ title: "7月1日", content: "曇り" },
{ title: "7月2日", content: "曇り時々晴れ" },
];
return <></>;
}
export default App;

return内に、ulタグを作成します。

ulの中でmenusmapで展開します。

jsx
return (
<>
<ul className="space-y-2">
{menus.map((menu, index) => (
))}
</ul>
</>
);

mapの中でliタグを作成します。 liの中で、ボタンとコンテンツの内容を作成します。

jsx
<ul className="space-y-2">
{menus.map((menu, index) => (
<li key={index} style={{ width: "240px" }}>
<button
type="button"
onClick={}
style={{
width: "100%",
textAlign: "center",
backgroundColor: "#ff8c00",
color: "#f1f1f1",
padding: "0.5rem",
}}
>
{menu.title}
</button>
<div>
{menu.content}
</div>
</li>
))}
</ul>

クリックすると、コンテンツ内容が表示されたり非表示になったりします。

どのボタンを押したかを判別するには、indexを使い、押されたindex番号とコンテンツ内のindex番号が一致すると開くようにします。

押されている番号を状態管理するために、useStateを使用します。

jsx
import React, { useState } from "react";

初期時は、どのコンテンツも開かないようにするために、index番号が該当しない数値にします。とりあえず今回は 3 つしかないので、該当しない番号である 100 を設定しました。

コンテンツが 200 ある場合は、useStateの中を 500 くらいにしましょう。

jsx
const [clicked, setClicked] = useState(100);

buttononClickhandleClickを設定します。

handleClickには、indexを渡すようにします。

jsx
<button
type="button"
onClick={() => handleClick(index)}
style={{
width: "100%",
textAlign: "center",
backgroundColor: "#ff8c00",
color: "#f1f1f1",
padding: "0.5rem",
}}
>

handleClickを作成します。

handleClickを実行すると、setClickedindexを渡すようにします。

jsx
function App() {
const [clicked, setClicked] = useState(100);
const menus = [
{ title: "6月30日", content: "晴れ" },
{ title: "7月1日", content: "曇り" },
{ title: "7月2日", content: "曇り時々晴れ" },
];
const handleClick = (index) => {
setClicked(index);
};

ボタンを 2 回押すと閉じるようにしたいので、クリックしたボタンのindex番号とclickedの番号が一致する場合、初期値に戻すようにします。

jsx
const handleClick = (index) => {
if (clicked === index) {
return setClicked(100);
}
setClicked(index);
};

ボタンの実装が完了したので、次は、コンテンツの表示・非表示を行います。

非表示の場合は高さを 0 にし、表示する場合はコンテンツの中身に合わせて高さを変えていきます。

コンテンツの中身の高さを取得するために、useRefを使用します。

reactからuseRefをインポートします。

jsx
import React, { useRef, useState } from "react";

useRefcontentElを作成します。

jsx
function App() {
const contentEl = useRef();

buttonの下のdivref属性を指定します。

jsx
<div ref={contentEl}>{menu.content}</div>

クリックしたボタンのindex番号とclickedの番号が一致する場合、heightcontentElcurrent.scrollHeightを指定します。

逆に一致しない場合、heightを 0 にし、overflowhiddenにします。

jsx
<div
ref={contentEl}
style={
clicked === index
? {
height: contentEl.current.scrollHeight,
backgroundColor: "#e7d0a9",
}
: { height: "0px", overflow: "hidden" }
}
>
{menu.content}
</div>

一通り完成したので、動作確認します。

image2

試しに 6 月 30 日をクリックすると、

image3

6 月 30 日のコンテンツのみ表示されました。

7 月 2 日をクリックすると、

image4

6 月 30 日のコンテンツが非表示になり、7 月 2 日のコンテンツが表示されました。

もう一度、7 月 2 日をクリックしてみると、

image5

全ての内容が非表示になりました。

© 2024あずきぱんウェブスタジオ