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

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

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

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

React.js

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

Q&A

解決済

1回答

2704閲覧

Reactで作るtodoアプリです

yuki_nagahama

総合スコア17

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

React.js

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

0グッド

0クリップ

投稿2016/12/19 15:27

現在ReactにてTodoアプリケーションを作っています。

<TodoApp> <TodoCreator /> <TodoList /> </TodoApp>

全体はTodoを作るアプリケーションで、その中にTodoCreatorにてinputフィールドとbuttonを設置していて、
inputに言葉を入力するとbuttonをクリックした時に全体の持つstateが増えて、TodoListにてリスト表示をしております。

完成画面です

この場合上のinputフィールドとbuttonがTodoCreatorで、
その下に表示されているリストはTodoListです。

※ここでどうしてもできない問題が発生しました。
Todolistに<Checkbox onClick={this._onChange.bind(this))} />
のように左側のチェックボックスをクリックした時にこのコンポーネントが持つ_onChangeが発火するはずなのですが、bindしても{::this._onChange}をしてもなぜか
_onChange of undifined
のエラーが出てしまうのです。。
(ちなみに、ES6構文のエラーは全て試しましたので、ロジック的にできないのかと考えております。)

理由はリストにて表示しているので、
構築した後のListにonclickをしてもデータの流れは一方通行だと聞いたことがあるので、
もしかするとそのような問題なのかなあと思っております。

完成目標では_onChange関数で、選択したリストは斜線を引くとい風にしたいのです。
どうかよろしくお願いいたします。

↓問題になっているコードです。

class TodoValue extends React.Component{ _onDelete(i){ console.log(i); } render(){ return( <List> { this.props.todos.map(function(todo, i){ return <ListItem key={i} primaryText={todo.item} rightIcon={<ActionInfo />} leftCheckbox={<Checkbox onClick={this._onDelete.bind(this, i)} />} /> }) } </List> ); } }

↓全文です。

import React from 'react'; import ReactDOM from 'react-dom'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; import injectTapEventPlugin from 'react-tap-event-plugin'; injectTapEventPlugin(); import TextField from 'material-ui/TextField'; import RaisedButton from 'material-ui/RaisedButton'; import {List, ListItem} from 'material-ui/List'; import Subheader from 'material-ui/Subheader'; import Divider from 'material-ui/Divider'; import Checkbox from 'material-ui/Checkbox'; import Toggle from 'material-ui/Toggle'; import ActionInfo from 'material-ui/svg-icons/action/info'; import { withGoogleMap } from "react-google-maps"; const style = { margin: 12, }; class TodoInput extends React.Component{ constructor(){ super(); this.state = { value: "" } } _onAdd(){ const newTodo = this.refs.inputText.getValue(); this.props.onAdd(newTodo) this.setState({ value: "" }); } _onChange(){ this.setState({ value: this.refs.inputText.getValue() }); } render(){ return( <div> <TextField hintText="ここにTodoを入力" ref="inputText" value={this.state.value} onChange={this._onChange.bind(this)} /> <RaisedButton label="追加" secondary={true} style={style} onClick={this._onAdd.bind(this)} /> </div> ); } } class TodoValue extends React.Component{ _onDelete(i){ console.log(i); } render(){ return( <List> { this.props.todos.map(function(todo, i){ return <ListItem key={i} primaryText={todo.item} rightIcon={<ActionInfo />} leftCheckbox={<Checkbox onClick={this._onDelete.bind(this, i)} />} /> }) } </List> ); } } class TodoApps extends React.Component{ constructor(){ super(); this.state = { todos: [] } this.onAdd = this.onAdd.bind(this); } onAdd(newTodo){ this.setState({ todos: this.state.todos.concat({item:newTodo, status:0}) }); } render(){ return( <MuiThemeProvider> <div> <TodoInput onAdd={this.onAdd} /> <TodoValue todos={this.state.todos} /> </div> </MuiThemeProvider> ); } } ReactDOM.render(<TodoApps />, document.getElementById("content"));

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

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

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

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

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

guest

回答1

0

ベストアンサー

JavaScript

1this.props.todos.map((todo, i) => { 2 return <ListItem key={i} primaryText={todo.item} rightIcon={<ActionInfo />} leftCheckbox={<Checkbox onClick={this._onDelete.bind(this, i)} />} /> 3})

と言う風に、mapに渡す関数についてアロー関数=>を使ってみてください。


【解説】

Array.property.mapに渡すコールバック関数について、その関数の実行時にthisはグローバルオブジェクト(windowやglobal)になります。そのため、mapでのコールバック関数内で相当通りのthisを使用する場合は、

  1. アロー関数=>を使う。
  2. 無名関数functionに対してbindを使って束縛する。
  3. mapに第二引数を与える。(第二引数でthisが束縛される)

のいずれかを行う必要があります。ES6以降またはTypeScriptやCoffeeScriptを使っている場合は、1.のアロー関数を使うのが短くて一番わかりやすいと思います。他のコールバック関数についても基本的にアロー関数を使うとした方が問題が起きにくいです。

参考: Array.prototype.map() - JavaScript | MDN

投稿2016/12/19 22:06

編集2016/12/19 22:07
raccy

総合スコア21733

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

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

yuki_nagahama

2016/12/20 00:42

アロー関数について詳しく教えていただきありがとうございました。 調べてもなかなかこの解決方法には至りませんでしたので、 1日で解決できたことすごく嬉しいです。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問