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

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

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

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

Q&A

解決済

1回答

1957閲覧

React リスト削除機能追加 エラーの解消

Kosuke0906

総合スコア13

React.js

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

0グッド

0クリップ

投稿2019/11/28 08:32

Reactのクリックしたら削除する関数を作って孫コンポーネントに渡そうとしたところこんなエラーが出てしまいました。

・removeTodos関数は孫コンポーネントまで渡っているはずです。
・削除ボタンクリックすると下記のエラー出現。

このエラーがなくなれば上手く削除出来るはずです...!
プログラミングって難しいですね。

#出現したエラー
`TypeError: props.todos.map is not a function
List
src/List.js:5
2 | import Item from "./Item";
3 |
4 | const List = props => {

5 | const todos = props.todos.map((todo, i) => {

6 | return <Item key={i} desc={todo} removeTodos={props.removeTodos} />;
7 | });
8 | return <ol>{todos}</ol>;
View compiled`

App

1import React from "react"; 2import Form from "./Form"; 3import List from "./List"; 4 5const App = () => { 6 const [todos, setTodos] = React.useState(["走る", "跳ぶ", "投げる"]); 7 const addTodos = text => { 8 const newTodos = [...todos, text]; 9 setTodos(newTodos); 10 }; 11 const removeTodos = (todo) => { 12 const arrayTodos=todos.slice(); 13 const posi = arrayTodos.indexOf(todo); 14 arrayTodos.splice(posi, 1); 15 setTodos({arrayTodos}); 16 }; 17 return ( 18 <div> 19 <Form addTodos={addTodos} /> 20 <List todos={todos} removeTodos={removeTodos} /> 21 </div> 22 ); 23}; 24 25export default App; 26

List

1import React from "react"; 2import Item from "./Item"; 3 4const List = props => { 5 const todos = props.todos.map((todo, i) => { 6 return <Item key={i} desc={todo} removeTodos={props.removeTodos} />; 7 }); 8return <ol>{todos}</ol>; 9}; 10export default List; 11 12

Item

1import React from "react"; 2import styled from "styled-components"; 3const Item = (props) => { 4 const [isDone, setIsDone] = React.useState(false); 5 const toggleIsDone = () => setIsDone(!isDone); 6 const buttonText = isDone ? "戻す" : "完了"; 7 const handleClick=(todo)=> props.removeTodos(todo); 8 9 10 return ( 11 <li> 12 <p>{props.desc}</p> 13 <Button onClick={toggleIsDone}>{buttonText}</Button> 14 <button onClick={handleClick}>削除</button> 15 {/* ↑↑↑でクリック&削除のイベントハンドラ設置 */} 16 </li> 17 ); 18}; 19const Button = styled.button` 20 border-radius: 3px; 21 border: 2px solid pink; 22 color: pink; 23 margin: 0 1em; 24 padding: 0.25em 2em; 25`; 26export default Item; 27

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんにちは

以下の2点、(1)(2)を修正してみると、いかがでしょうか?

(1) Item の handleClick

修正前

javascript

1const handleClick=(todo)=> props.removeTodos(todo); 2

修正後

javascript

1const handleClick = () => props.removeTodos(props.desc);

(2) App の removeTodos で setTodos する箇所

修正前

javascript

1setTodos({arrayTodos}); 2

修正後

javascript

1setTodos(arrayTodos);

以下は、ご質問のコードをCodePenに転記して、さらに上記2点の修正をしたものです。

参考になれば幸いです。

補足

filter を使うと、 removeTodos は、以下のように書けます。

javascript

1 const removeTodos = (todo) => { 2 setTodos(todos.filter(e => e !== todo)); 3 };

上記の場合、引数の todo に一致するものが todos に複数あった場合、それらの全てが除外された配列で、todosを更新します。

投稿2019/11/28 13:42

編集2019/11/28 14:10
jun68ykt

総合スコア9058

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

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

Kosuke0906

2019/11/28 14:07

動きました!! ありがとうございます! 自分も早く教えられるようになります。????
jun68ykt

2019/11/28 14:11

どういたしまして。 > 動きました!! とのことでよかったです????
Kosuke0906

2019/11/28 14:58

補足事項の方が便利ですね! 同じ要素があるときこちらじゃないと不便です!
jun68ykt

2019/11/29 01:11

はい。 > 同じ要素が あり得る場合、ちょっと考慮しないといけない点がありますね。 たとえば、todos の初期値の配列に、 もうひとつ "走る" を末尾に追加して const [todos, setTodos] = React.useState(["走る", "跳ぶ", "投げる", "走る"]); というものにして、 走る 跳ぶ 投げる 走る という初期状態から、(先頭ではなく)末尾の "走る" を削除しようとしたときにどうなるか、考えてみます。 まず、ご質問に挙げられているほうの const removeTodos = (todo) => { const arrayTodos=todos.slice(); const posi = arrayTodos.indexOf(todo); arrayTodos.splice(posi, 1); setTodos(arrayTodos); }; で削除すると、期待している 走る 跳ぶ 投げる ではなくて、 跳ぶ 投げる 走る になります。つまり、末尾の「走る」ではなく、先頭の「走る」が削除されてしまいます。これは、 indexOf が引数と同じ値の要素のうち、最初のもののインデクスを返すからです。 では、私が回答に追記したほうの filterを使った const removeTodos = (todo) => { setTodos(todos.filter(e => e !== todo)); }; だとどうなるかというと、先頭と末尾の「走る」がともに削除されて、 跳ぶ 投げる になってしまいます。つまり、どちらにしても、ちょっと望ましい結果とは言えないですよね? ですので、ご質問にあるコードをベースとして、次の課題として、初期値として ["走る", "跳ぶ", "投げる", "走る"] を与えて、末尾(=インデクスが3)の「走る」を削除しようとしたときに、末尾の「走る」だけがtodosから除外されるように修正してみるというのをやってみるとよいかもしれません。
Kosuke0906

2019/11/29 11:49

丁寧にありがとうございます! すごくわかりやすいです。 個人レッスンみたいで、 やる気がかなり上がりますね! なんとかやりきります!!
jun68ykt

2019/11/29 13:02

もし、上記の”末尾の「走る」だけを除外する” ように修正することに挑戦してみたけれども上手く出来なかった、ということになったら、その「上手くいくと思ってやりかけたが、分からなくなった」という時点でのコードを添えて、新たにご質問されるとよいでしょう。Good luck to you !
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問