質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

521閲覧

ボタンをクリックするとその配列に対して表示される機能を実装したい

naokoo

総合スコア1

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2022/09/11 04:07

前提

reactで各ボックスに付随したボタンをクリックするとそのボックス内容が表示・非表示する機能を作りたいです。

実現したいこと

<button>クリック1</button>

<p>テキスト1</p>

<button>クリック2</button>

<p>テキスト2</p>

<button>クリック3</button>

<p>テキスト3</p>

・クリック1を押すと、テキスト1が表示/非表示になる
・クリック2を押すと、テキスト2が表示/非表示になる
・クリック3を押すと、テキスト3が表示/非表示になる

発生している問題・エラーメッセージ

エラーメッセージ
Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more:

該当のソースコード

import React, { useState } from "react";
import "./styles.css";

export const App = () => {
const textArr = ["テキスト1", "テキスト2", "テキスト3"];
const [open, setOpen] = useState(false);

const onClickOpen = (index) => {
setOpen(!open[index]);
};
return (
<>
{textArr.map((text, index) => {
return (
<div key={text}>
<button onClick={() => onClickOpen(index)}>クリック</button>
{open[index] && <p>{text}</p>}
</div>
);
})}
</>
);
};

試したこと

配列のindexを伴わないものは作成できました。
その場合、クリック1を押すと、テキスト2とテキスト3も開いてしまいます。
押したボタンのボックスに対してのテキストを表示・非表示したいので、indexで指定したいのですが、上手く動作しません。
わかる方教えていただきたいです。

補足情報(FW/ツールのバージョンなど)

コードサンドボックスを使用しています。
react 18.2.0
react-dom 18.2.0
react-scripts 4.0.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

配列textArrの要素の数と同じ個数の要素を持つブール値の配列をuseStateで作成して、ボタンがクリックされたときに、クリックされたボタンのインデクスにあるブール値によって表示、非表示を切り替えるとよいです。たとえばこんな感じです:

jsx

1const App = () => { 2 const textArr = ["テキスト1", "テキスト2", "テキスト3"]; 3 const [visibilities, setVisibilities] = useState([...Array(textArr.length)].map(_ => false)); 4 5 const handleClick = (index) => { 6 setVisibilities(prevState => prevState.map((v, i) => index === i ? !v : v)); 7 } 8 9 return( 10 <div> 11 {visibilities.map((visible, i) => ( 12 <div key={textArr[i]}> 13 <button onClick={() => handleClick(i)}> 14 クリック 15 </button> 16 {visible && <p>{textArr[i]}</p>} 17 </div> 18 ))} 19 </div> 20 ); 21}

サンプル 👉 https://codepen.io/su507/pen/NWMrrRK?editors=0010

補足1

<div key={textArr[i]}> としているので、textArr は同じ文字列を要素として持っていないことが前提になります。もしtextArr は同じ文字列を要素として持っていると「keyが重複している」旨の警告が表示されることになると思われます。

補足2

上記の回答コードの中で長さが textArr.length で値がすべてfalseの配列を作るところは

javascript

1[...Array(textArr.length)].map(_ => false)

としていましたが、手短かに以下で済んでました。

javascript

1textArr.map(_ => false)

CodePenのサンプルは上記のように修正済みです。

補足3

テキストの表示、非表示切り替えの別のやり方として、テキストを囲んでいる <p> の style の display を、none または block で切り替えるという方法もあります。参考程度に眺めてください👉 https://codepen.io/su507/pen/qBYNNvJ?editors=0010

投稿2022/09/11 05:08

編集2022/09/11 09:08
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naokoo

2022/09/11 06:07

ご丁寧に教えていただきありがとうございました。 ループする際は、下記の考え方が大事だと理解しました。 ・各ボタンについてのステート定義 ・各ボタンをクリックした際にステートの定義が切り替わる
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問