🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

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

Q&A

解決済

1回答

2258閲覧

reactを使ったtodoアプリにてチェックボックスをチェック後、ボタンをクリックしてチェックされた箇所を削除したい!

suzukitoshinari

総合スコア6

Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

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

0グッド

0クリップ

投稿2021/01/12 09:38

編集2021/01/12 14:14

前提・実現したいこと

現在reactでtodo形式の単語登録アプリを作成しています。
チェックボックスでチェックした後に、削除ボタンを押したら該当箇所を削除したいのですが、できません。
かれこれ一カ月試行錯誤しましたができませんでした。

該当のソースコード

import React, { useState } from 'react'; import { makeStyles } from '@material-ui/core/styles'; import{ TextField, List, ListItem, Checkbox } from '@material-ui/core'; const useStyles = makeStyles({ root: { width: '100%', }, modal: { display: 'flex', alignItems: 'center', justifyContent: 'center', }, paper: { backgroundColor: 'white', border: '2px solid #000', boxShadow: 5, padding: 3 }, btn: { width: '100%' }, main: { width: '70%', height: '70%' }, list: { width: '80%', padding: 0, backgroundColor: 'white', border: '1px solid black', }, container: { display: 'flex', }, item: { borderBottom: '1px solid black', height: 40 } }); // const id = lists.length; const StickyTable = () => { const classes = useStyles(); const [words, setWord] = useState([]), [newWord, setNewWord] = useState(''), [meanings, setMeaning] = useState([]), [newMeaning, setNewMeaning] = useState(''); const handleNewWord = (e) => { setNewWord(e.target.value); } const handleNewMeaning = (e) => { setNewMeaning(e.target.value); }; const koko = () => { if(words && newWord === '' || newMeaning === '') { alert('単語と意味の両方を入力してください。'); setNewWord(''); setNewMeaning(''); return; } else if(newWord.match(/[^A-Za-z0-9]+/)) { alert('英語で入力してください。'); setNewWord(''); setNewMeaning(''); return; } else { handleAddWord(); handleAddMeaning(); } } const onClickAdd = () => {  koko(); } const handleAddWord = () => { // e.preventDefault() // const id = words.length ? words[words.length - 1].id + 1 : 0; setWord([...words, { id: Date.now(), item: newWord, isCompleted: false }]) setNewWord(''); } const handleAddMeaning = () => { // e.preventDefault() // const id = meanings.length ? meanings[meanings.length - 1].id + 1 : 0; setMeaning([...meanings, { id: Date.now(), content: newMeaning, isCompleted: false }]) setNewMeaning(''); } const handleDeleteWord = (id) => { // const id = words.length ? words[words.length - 1].id + 1 : 0; setWord(words.filter((word) => word.id !== id)); } const handleDeleteMeaning = (id) => { setMeaning(meanings.filter((meaning) => meaning.id !== id)); } const onClickDelete = () => { handleDeleteWord(); handleDeleteMeaning(); } const toggleDeleteWord = (id) => { setWord(words.map(word => { if (word.id === id) { return {...word, isCompleted: !word.isCompleted} } return word })) } const toggleDeleteMeaning = (id) => { setMeaning(meanings.filter(meaning => { if (meaning.id === id) meaning.isCompleted = !meaning.isCompleted return meaning })) } const toggleDelete = (id) => { toggleDeleteWord(id); toggleDeleteMeaning(); } return ( <> <div className={classes.main}> <form className={classes.paper} autoComplete='off'> <TextField label='単語' value={newWord} onChange={handleNewWord}/> <TextField label='意味' value={newMeaning} onChange={handleNewMeaning}/> <button type='button' onClick={onClickAdd}> 登録する </button> <button onClick={onClickDelete}> 削除 </button> </form> <div className={classes.container}> <List component='ol' className={classes.list}> {words.map((word, id) => ( <ListItem key={id} component='li' className={classes.item}> <Checkbox color="primary" inputProps={{ 'aria-label': 'secondary checkbox' }} onClick={toggleDelete} defaultChecked={word.isCompleted} /> {word.item} </ListItem> ))} </List> <List component='ol' className={classes.list}> {meanings.map((meaning, id) => ( <ListItem key={id} component='li' className={classes.item}> {meaning.content} </ListItem> ))} </List> {/* <div> // {items.length} items // </div> */} </div> </div> </> ); } export default StickyTable; コード

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

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

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

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

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

hoshi-takanori

2021/01/12 11:19

「チェックしたら該当箇所を削除したい」とのことですが、チェックボックスをクリックしたら、いきなりその項目を削除したいということでしょうか?
suzukitoshinari

2021/01/12 11:33

質問見ていただきありがとうございます。 実現したい内容としてはチェックした後に、削除ボタンを押したらチェック項目を削除するという挙動です。
guest

回答1

0

ベストアンサー

気になる点がいっぱいあったので、書き直してみました。

  • id に Date.now() を使うのは良くないので、uuid を使いましょう。(uuid パッケージを追加してください。)
  • words と meanings の配列を分けると面倒くさいので、ひとつにしました。また、名前も items にして、各 item が id, word, meaning, isCompleted を持つようにしました。
  • 入力エラー時に入力内容を消されると悲しいので、消さないようにしてみました。
  • 削除ボタンに type='button' がないためにリロードされていたのを修正しました。
  • 削除ボタンを押したらチェックされた項目をすべて削除するようにしました。(削除ボタンは一つしかないので、削除時に id を指定して削除するのは難しいと思います。)
  • リストの要素を map で作る場合の key には、index ではなく id を指定するのが望ましいです。
  • チェックボタンを on/off した時は、その単語の id を引数として toggleCompleted を呼び出すようにしました。(こういう場合、onClick に関数そのままではなくクロージャを渡す必要があります。)
  • チェックボタンの値は value で設定して 制御されたコンポーネント にしました。
  • word と meaning のリストが別になってますが、一つのまとめた方がいいと思います。(未対応)

js

1import React, { useState } from 'react'; 2import { makeStyles } from '@material-ui/core/styles'; 3import { TextField, List, ListItem, Checkbox } from '@material-ui/core'; 4import { v4 as uuidv4 } from 'uuid'; 5 6const useStyles = makeStyles({ 7 // 略 8}); 9 10const StickyTable = () => { 11 const classes = useStyles(); 12 13 const [items, setItems] = useState([]), 14 [newWord, setNewWord] = useState(''), 15 [newMeaning, setNewMeaning] = useState(''); 16 17 const handleNewWord = (e) => { 18 setNewWord(e.target.value); 19 } 20 const handleNewMeaning = (e) => { 21 setNewMeaning(e.target.value); 22 }; 23 24 const onClickAdd = () => { 25 if (newWord === '' || newMeaning === '') { 26 alert('単語と意味の両方を入力してください。'); 27 return; 28 } else if(newWord.match(/[^A-Za-z0-9]+/)) { 29 alert('英語で入力してください。'); 30 return; 31 } else { 32 handleAddWord(); 33 } 34 } 35 36 const handleAddWord = () => { 37 setItems([...items, { 38 id: uuidv4(), word: newWord, meaning: newMeaning, isCompleted: false 39 }]); 40 setNewWord(''); 41 setNewMeaning(''); 42 } 43 44 const onClickDelete = () => { 45 setItems(items.filter((item) => !item.isCompleted)); 46 } 47 48 const toggleCompleted = (id) => { 49 setItems(items.map(item => { 50 if (item.id === id) { 51 return {...item, isCompleted: !item.isCompleted} 52 } 53 return item 54 })); 55 } 56 57 return ( 58 <> 59 <div className={classes.main}> 60 <form className={classes.paper} autoComplete='off'> 61 <TextField label='単語' value={newWord} onChange={handleNewWord}/> 62 <TextField label='意味' value={newMeaning} onChange={handleNewMeaning}/> 63 <button type='button' onClick={onClickAdd}> 64 登録する 65 </button> 66 <button type='button' onClick={onClickDelete}> 67 削除 68 </button> 69 </form> 70 <div className={classes.container}> 71 <List component='ol' className={classes.list}> 72 {items.map((item) => ( 73 <ListItem key={item.id} component='li' className={classes.item}> 74 <Checkbox 75 color="primary" 76 inputProps={{ 'aria-label': 'secondary checkbox' }} 77 onClick={e => toggleCompleted(item.id)} 78 value={item.isCompleted} 79 /> 80 {item.word} 81 </ListItem> 82 ))} 83 </List> 84 <List component='ol' className={classes.list}> 85 {items.map((item) => ( 86 <ListItem key={item.id} component='li' className={classes.item}> 87 {item.meaning} 88 </ListItem> 89 ))} 90 </List> 91 {/* <div> 92 // {items.length} items 93 // </div> */} 94 </div> 95 </div> 96 </> 97 ); 98} 99 100export default StickyTable;

投稿2021/01/12 14:23

hoshi-takanori

総合スコア7899

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

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

suzukitoshinari

2021/01/13 05:34

ありがとうございます!本当にずっと解決せずに悩んでたので感謝です!独学つらいですががんばれそうです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問