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

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

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

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

Q&A

解決済

1回答

748閲覧

Reactにて、一度でもクラスを付与すると、期待とは異なる要素が削除されてしまいます

退会済みユーザー

退会済みユーザー

総合スコア0

React.js

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

0グッド

0クリップ

投稿2020/04/07 04:44

実現したいこと

ADDボタンを押すとTodoリストが追加されて、removeボタンを押すとそのTodoリストが削除されます。
iconをクリックするとis-activeクラスが着脱します。

  • iconをクリックするまでは不具合が起こりません。
  • 一度でもiconをクリックしてis-activeクラスを付与すると、期待とは異なる要素が削除されるようになってしまいました。消える要素の規則性はないように見えます
removeTodo = (index) => { const {todos} = this.state; this.setState({ todos: [...todos.slice(0, index), ...todos.slice(index + 1)] }); } render() { return( <> <div className="l-flex form"> <Form onChangeFunction={this.changeValue} value={this.state.value} /> <Btn text="ADD!" onClickFunction={this.addTodo} /> </div> <TodoList todos={this.state.todos} onClickFunction={this.removeTodo} /> </> ); }
const TodoList = (props) => { return( <ul className="list l-flex"> {props.todos.map((todo, index) => <List onClickFunction={props.onClickFunction} key={index} todo={todo} index={index} /> )} </ul> ); }
changeActive = () => { this.setState({ active: !this.state.active, }); } render() { return( <li className={"list-item l-flex" + (this.state.active ? " is-active" : "")} > <i onClick={this.changeActive} className={"far list-icon" + (this.state.active ? " fa-check-square" : " fa-square")}></i> <p>{this.props.todo}</p> <Btn text="remove!" onClickFunction={() => this.props.onClickFunction(this.props.index)} /> </li> ); }

調べてみたこと

this.props.indexの値をconsole.log()で見てみました。
例えばリストが三つあって更にADDボタンを押してリストを追加する→0,1,2,3と全ての値が一度ずつ呼ばれました。

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

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

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

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

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

hoshi-takanori

2020/04/07 08:17

こちらで試した限りでは問題なく動いてるように見えますけど…。
退会済みユーザー

退会済みユーザー

2020/04/08 03:13

https://nakamura0907.github.io/react_todo/public/ リンクです。 5つほどTodoリストを追加して真ん中のリストにis-activeを付与してみてください。そしてis-activeを付与したリストを削除しようとして見てください。 全く異なるリストが削除されてしまいます…
guest

回答1

0

ベストアンサー

List の key が index のため、削除するとその後ろの内容がずれてしまってますね。
解決方法は以下の 3 種類 (ただし 1 は不完全) でしょう。

  1. List の key を index ではなく todo とする (同じ名前の todo があると駄目)
  2. todo の各項目に一意な id を持たせる
  3. active を List の state ではなく、todo の属性にする

例えば、todos = ['aaa', 'bbb', 'ccc'] で、bbb にチェックしたとします。

<List key={0} todo='aaa' index={0} /> <!-- state = { active: false } --> <List key={1} todo='bbb' index={1} /> <!-- state = { active: true } --> <List key={2} todo='ccc' index={2} /> <!-- state = { active: false } -->

ここで aaa を削除すると、次のようになります。

<List key={0} todo='bbb' index={0} /> <!-- state = { active: false } --> <List key={1} todo='ccc' index={1} /> <!-- state = { active: true } -->

つまり、<List key={2} /><List key={1} /><List key={1} /><List key={0} /> になる (active の値も移動する) のではなく、<List key={0} /><List key={1} /> は active の値も含め、そのままの位置で、todo の文字列だけが書き変わる (<List key={2} /> はなくなる) ために、期待とは異なる要素が削除されたように見えています。


とりあえず 2 の方法で修正する場合、まず npm install uuid して、Todo.tsx と TodoList.tsx をそれぞれ以下のように書き換えればいいと思います。

diff

1@@ -1,12 +1,18 @@ 2 import * as React from 'react'; 3+import { v4 as uuidv4 } from 'uuid'; 4 5 import Btn from '../presentational/atoms/Btn'; 6 import Form from '../presentational/atoms/Form'; 7 import TodoList from '../presentational/molecules/TodoList'; 8 9+interface TodoItem { 10+ id: string; 11+ value: string; 12+} 13+ 14 interface IState { 15 count: number; 16- todos: string[]; 17+ todos: TodoItem[]; 18 value: string; 19 } 20 21@@ -24,7 +30,7 @@ export default class Todo extends React.Component<{}, IState> { 22 addTodo = () => { 23 const {todos, value } = this.state; 24 this.setState({ 25- todos: [...todos, value] 26+ todos: [...todos, { id: uuidv4(), value } ] 27 }) 28 } 29

diff

1@@ -6,7 +6,7 @@ const TodoList = (props) => { 2 return( 3 <ul className="list l-flex"> 4 {props.todos.map((todo, index) => 5- <List onClickFunction={props.onClickFunction} key={index} todo={todo} index={index} /> 6+ <List onClickFunction={props.onClickFunction} key={todo.id} todo={todo.value} index={index} /> 7 )} 8 </ul> 9 );

投稿2020/04/08 06:51

編集2020/04/08 06:53
hoshi-takanori

総合スコア7901

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

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

退会済みユーザー

退会済みユーザー

2020/04/08 08:20

ありがとうございます!不具合がなくなりました!! 今回のような問題が発生していなくても、keyにはuuidを使って一意なidを設定するべきなのでしょうか?
hoshi-takanori

2020/04/08 08:24

今回の問題が生じたのは List が state を持ち、かつ削除が発生するからですねー。 key はできるだけ一意にすることが望ましいのですが、たぶん uuid はやりすぎで、API の結果とかならもともと id があるのが普通だし、表示だけなら index でもそんなに問題ない気がします。
退会済みユーザー

退会済みユーザー

2020/04/08 08:52

なるほど、確かに今までは問題が発生していませんでした。状況に応じて上手く使い分けたいと思います。 本当に困っている問題でした。ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問