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

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

詳細はこちら
JavaScript

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

React.js

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

Q&A

解決済

2回答

366閲覧

React.js mapのつかいかたについて。 教えて下さい!

tomomari

総合スコア28

JavaScript

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

React.js

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

0グッド

0クリップ

投稿2019/11/25 05:31

前提・実現したいこと

以下のサイトで紹介されているToDOアプリを作っています。
[参考記事]

React.jsでbuttonをクリックされたときに、入力内容をリストに追加するプログラムを実装中にエラーが起きました。

mapについてのエラーです。

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

todos.map is not a function

該当のソースコード

React.js

1コimport React, {Component} from 'react'; 2import logo from './logo.svg'; 3import './App.css'; 4 5const App = () =>{ 6 return<Todo /> 7} 8 9class Todo extends Component{ 10 11 constructor(props){ 12 super(props); 13 14 // thisの中にこういう数列をこういう初期値で用意しますよ 15 this.state ={ 16 todos: [], 17 name: '' 18 }; 19 } 20 21 addTodo = () => { 22 const{todos,name}=this.state; 23 this.setState({ 24 todos: {...todos,name} 25 }); 26 } 27 28 29 30render(){ 31 const {todos} = this.state; 32 33 return (<div> 34 <input type="text" onInput={this.onInput}/> 35 <button onClick={this.addTodo}>登録</button> 36 <ul> 37 {/* mapでリストに変換 */} 38 {todos.map((todo,index) => <li key ={index}> {todo} </li> )} 39 </ul> 40 41 </div>); 42} 43} 44export default App; 45

### 回答お願いいたします!
初心者で困っています。何が悪いのでしょうか、おしえてください!

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

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

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

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

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

guest

回答2

0

js

1 this.setState({ 2 todos: {...todos,name} 3 });

ここでスプレッドを使ってしまっているので、todosが配列ではなくなってしまいます。todos.concat([{/* 目的のオブジェクト */}])のような形にして、配列を維持したまま更新を行いましょう。

投稿2019/11/25 05:34

maisumakun

総合スコア145977

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

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

tomomari

2019/11/25 07:10

配列のまま操作する必要があるのがよくわかりました。ありがとうございます! 対応する場所を以下のように変更しました。 addTodo = () => { const{todos,name}=this.state; this.setState({ todos.concat([{...todos,name}]) }); } すると、todos.concatの[.]のところでエラーが出て、Failed to Compile と言われてしまいました。 お手数ですが、JSの知識がまだないので対応する場所を、書き換えていただけないでしょうか?
guest

0

ベストアンサー

だいぶ前の質問ですが、検索から飛んできた人のためにも一応回答しておきます(未だに回答受付中だし)。

スプレッド構文(...<これを使うやつ)はオブジェクトリテラルの内側で使うとオブジェクトとしてコピーされます。
配列としてコピーするには配列リテラルの内側で使う必要があります。

スプレッド構文 - JavaScript | MDN

スプレッド構文と似てるけど別物なやつがあります。混同しがちなので存在だけ知らせておきます。
分割代入 - JavaScript | MDN

js

1const array1 = ["one", "two", "three"]; 2const array2 = ["zero", ...array1, "four"]; 3console.log(array2); // ["zero", "one", "two", "three", "four"] 4 5const object1 = { hoge: 10, huga: 20 }; 6const object2 = { ...object1, piyo: 30 }; 7console.log(object2); // { hoge: 10, huga: 20, piyo: 30 } 8 9const object3 = { ...array1, piyo: 30 }; 10console.log(object2); // { 0: "one", 1: "two", 2: "three", piyo: 30 }

また、concatを使ってarray2と同じことをしようとするとこうなります。

js

1const array2 = ["zero"].concat(array1).concat(["four"]);

concatでもできますが、スプレッド構文の方が直感的で複数回連結する場合にもわかりやすいのでスプレッド構文をおすすめします。
なのでこの場合の正解はこうですね。(nameをリセットしてないですが)

js

1addTodo = () => { 2 const { todos, name } = this.state; 3 this.setState({ 4 todos: [...todos, name] 5 }); 6}

ただ実は、addTodoが複数回呼ばれた場合todosの参照が古いままなので一つしか追加されません。
この問題に対応したのが下記です。
同じToDoが複数追加されても困るので、この場合はこのままでもいいかもしれませんが。

js

1addTodo = () => { 2 this.setState(state => ({ 3 todos: [...state.todos, state.name] 4 })); 5}

あと全く別の話ですがnameは意味が広すぎるため、newTodoなどとすることをおすすめします。
後で読み直すとき格段にわかりやすくなります。

投稿2021/06/25 10:24

ka2obushi

総合スコア173

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問