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

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

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

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

JavaScript

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

React.js

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

Q&A

1回答

2905閲覧

Todoリストのグループ追加処理が上手くいかない

y_aka

総合スコア11

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

JavaScript

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

React.js

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

0グッド

2クリップ

投稿2019/03/16 07:25

編集2022/01/12 10:55

現在React Reduxを使用し簡易Todoアプリを作成している者です。
表題の通りTodoのグループを追加したいのですが
下記エラーが発生します。reduxdevToolsでstateのgroupListには
{id: "group-2", label: "グループ2"}
は追加されているのですがどこに原因があるのかわからないでいます。
エラー内容

bundle.js:30 TypeError: Cannot read property 'state' of undefined at Function.mapToProps (bundle.js:47) at r (bundle.js:47) at Function.r.mapToProps (bundle.js:47) at r (bundle.js:47) at bundle.js:47 at r.selectDerivedProps (bundle.js:47) at r.u.renderWrappedComponent (bundle.js:47) at r.u.indirectRenderWrappedComponent (bundle.js:47) at Ai (bundle.js:30) at qu (bundle.js:30) pu @ bundle.js:30 n.callback @ bundle.js:30 ou @ bundle.js:30 ru @ bundle.js:30 Bu @ bundle.js:30 Vu @ bundle.js:30 (anonymous) @ bundle.js:30 t.unstable_runWithPriority @ bundle.js:39 ja @ bundle.js:30 Na @ bundle.js:30 Pa @ bundle.js:30 ka @ bundle.js:30 Zu @ bundle.js:30 La @ bundle.js:30 Ma @ bundle.js:30 Wa.render @ bundle.js:30 (anonymous) @ bundle.js:30 Aa @ bundle.js:30 $a @ bundle.js:30 render @ bundle.js:30 (anonymous) @ bundle.js:47 n @ bundle.js:1 (anonymous) @ bundle.js:1 (anonymous) @ bundle.js:1 bundle.js:47 Uncaught TypeError: Cannot read property 'state' of undefined at Function.mapToProps (bundle.js:47) at r (bundle.js:47) at Function.r.mapToProps (bundle.js:47) at r (bundle.js:47) at bundle.js:47 at r.selectDerivedProps (bundle.js:47) at r.u.renderWrappedComponent (bundle.js:47) at r.u.indirectRenderWrappedComponent (bundle.js:47) at Ai (bundle.js:30) at qu (bundle.js:30)

該当するソース reducer.js

import { todoActionNames } from "../actions/todoActions"; import { groupActionNames } from "../actions/groupActions"; import _ from "lodash"; const initialState = { groupList: [ { id: "inbox", label: "受信箱" }, { id: "group-1", label: "グループ1" }, { id: "group-2", label: "グループ2" } ], todoList: { "inbox": [ { id: "item-1", label: "Todo1", completed: false }, { id: "item-2", label: "Todo2", completed: false } ], "group-1": [ { id: "item-3", label: "Todo3", completed: false }, { id: "item-4", label: "Todo4", completed: false } ] }, todoCount: 4, groupCount: 1, selectedGroup: "group-1" } const reducer = (state = initialState, action) => { let _state = _.cloneDeep(state); let todoList = []; switch (action.type) { case todoActionNames.ADD_TODO: _state.todoCount++; todoList = _state.todoList[_state.selectedGroup]; let todoItem = { id: "item-" + _state.todoCount, label: action.payload.data, completed: false } todoList.push(todoItem); return _state; case todoActionNames.COMPLETE_TODO: todoList = _state.todoList[_state.selectedGroup]; for (var i = 0; i < todoList.length; i++) { if (todoList[i].id == action.payload.id) { todoList[i].completed = true; break; } } return _state; case todoActionNames.DELETE_TODO: todoList = _state.todoList[_state.selectedGroup]; for (var i = 0; i < todoList.length; i++) { if (todoList[i].id == action.payload.id) { todoList.splice(i, 1); break; } } return _state; case groupActionNames.ADD_GROUP: _state.groupCount++; let groupId = "group-" + _state.groupCount; let groupItem = { id: groupId, label: action.payload.data } _state.groupList.push(groupItem); _state.todoList[groupId] = []; return _state; default: return state; } } export default reducer;

追記

containers\sideArea.js

import { connect } from "react-redux"; import { groupActions } from "../actions/groupActions"; import SideArea from "../components/sideArea"; const mapStateToProps = (state) => { return { groupList: state.groupList } } const mapDispatchToProps = (dispatch) => { return { onAddGroup: (data) => { dispatch(groupActions.addGroup(data)); } } } export default connect( mapStateToProps, mapDispatchToProps )(SideArea)

actions/groupAction.js

export const groupActionNames = { ADD_GROUP: "ADD_GROUP" } export const groupActions = { addGroup: (data) => { return { type: groupActionNames.ADD_GROUP, payload: { data: data } } } }

components/sideArea.js

import React from "react"; import ReactDOM from "react-dom"; import AddGroupDialog from "./addGroupDialog"; import EditGroupDialog from "./editGroupDialog" export default class SideArea extends React.Component { constructor(props) { super(props); this.state = { showAddGroupDialog: false, showEditGroupDialog: false, selectedGroup: undefined } } onClickGroup(event) { let listItem = ReactDOM.findDOMNode(event.target); let id = listItem.dataset.id; this.props.onSelect(id); } onClickAddGroup(event) { this.setState({ showAddGroupDialog: true }); } onSaveAddGroupDialog(groupName) { console.log("onSaveAddGroupDialog", groupName); this.props.onAddGroup(groupName); this.setState({ showAddGroupDialog: false }); } onCancelAddGroupDialog() { this.setState({ showAddGroupDialog: false }); } onSaveEditGroupDialog(id, groupName) { this.props.onEditGroup(id, groupName); this.setState({ showEditGroupDialog: false }); } onCancelEditGroupDialog() { this.setState({ showEditGroupDialog: false }); } onDeleteEditGroupDialog(id) { this.props.onDeleteGroup(id); this.setState({ showEditGroupDialog: false }); } onClickGroupEdit(event) { let editButton = ReactDOM.findDOMNode(event.target); let id =editButton.dataset.id; let selectedGroup; for (let i = 0; i < this.props.groupList.length; i++) { if (this.props.groupList[i].id === id) { selectedGroup = this.props.groupList[i]; break; } } this.setState({ showEditGroupDialog: true, selectedGroup: selectedGroup }); } renderGroup() { let groupListDom = []; for (let i = 0; i < this.props.groupList.length; i++) { let group = this.props.groupList[i]; let groupItem = (<li key={group.id}> <span data-id={group.id} onClick={this.onClickGroup.bind(this)}> {group.label}</span> <button data-id={group.id} className="group-edit-button" onClick={this.onClickGroupEdit.bind(this)}>編集</button> </li>); groupListDom.push(groupItem); } return groupListDom; } render() { return ( <div className="side-area"> <ul className="group-list"> {this.renderGroup()} </ul> <div className="side-area-footer"> <button className="add-group-button" onClick={this.onClickAddGroup.bind(this)}>グループ新規作成</button> </div> <AddGroupDialog show={this.state.showAddGroupDialog} onSave={this.onSaveAddGroupDialog.bind(this)} onCancel={this.onCancelAddGroupDialog.bind(this)} /> <EditGroupDialog show={this.state.showEditGroupDialog} group={this.state.selectedGroup} onSave={this.onSaveEditGroupDialog.bind(this)} onCancel={this.onCancelEditGroupDialog.bind(this)} onDelete={this.onDeleteEditGroupDialog.bind(this)} /> </div> ) } }

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

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

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

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

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

alpaka

2019/03/17 00:52

Reduxのstateを呼び出しているコンポーネントのコードも貼ってもらえますか? そこに原因があるかも
y_aka

2019/03/17 01:06

関連のあるコードを追加させていただきました。 宜しくお願いします。
alpaka

2019/03/17 01:21

ReduxのStateを呼び出しているコンポーネントが見当たらないですが、これで全てですか? ちなみにmapStateToProps,mapStateToDispatchしているコンポーネント内のpropsでReduxのStateを呼び出します。
y_aka

2019/03/17 01:41

理解が乏しくすみません、追記しました。 宜しくお願いします。
alpaka

2019/03/17 02:09

これは何の情報を参考にかきましたか? 私の知っているReact/Reduxの書き方ではないので、根本的に色々間違っている気がします。
y_aka

2019/03/17 02:15

そうなんですか。 Udemyの教材を元に学習しています。Udemy教材のQ&Aにも質問しているので確認してみます。
guest

回答1

0

エラー自体はComponentとContainerで2つsideArea.jsを作っていて、Reduxの連携ができていないからだと思います。
コンポーネントを呼び出す際containerのsideAreaを呼び出すはずが、Reduxと連携されていないcompoentのsideAreaを呼び出していませんか?
ひとつにまとめちゃってよいかと

import React from "react"; import ReactDOM from "react-dom"; import AddGroupDialog from "./addGroupDialog"; import EditGroupDialog from "./editGroupDialog" //追記 import { connect } from "react-redux"; import { groupActions } from "../actions/groupActions"; // 文頭のexportを削除 class SideArea extends React.Component { constructor(props) { super(props); this.state = { showAddGroupDialog: false, showEditGroupDialog: false, selectedGroup: undefined } } onClickGroup(event) { let listItem = ReactDOM.findDOMNode(event.target); let id = listItem.dataset.id; this.props.onSelect(id); } onClickAddGroup(event) { this.setState({ showAddGroupDialog: true }); } onSaveAddGroupDialog(groupName) { console.log("onSaveAddGroupDialog", groupName); this.props.onAddGroup(groupName); this.setState({ showAddGroupDialog: false }); } onCancelAddGroupDialog() { this.setState({ showAddGroupDialog: false }); } onSaveEditGroupDialog(id, groupName) { this.props.onEditGroup(id, groupName); this.setState({ showEditGroupDialog: false }); } onCancelEditGroupDialog() { this.setState({ showEditGroupDialog: false }); } onDeleteEditGroupDialog(id) { this.props.onDeleteGroup(id); this.setState({ showEditGroupDialog: false }); } onClickGroupEdit(event) { let editButton = ReactDOM.findDOMNode(event.target); let id =editButton.dataset.id; let selectedGroup; for (let i = 0; i < this.props.groupList.length; i++) { if (this.props.groupList[i].id === id) { selectedGroup = this.props.groupList[i]; break; } } this.setState({ showEditGroupDialog: true, selectedGroup: selectedGroup }); } renderGroup() { let groupListDom = []; for (let i = 0; i < this.props.groupList.length; i++) { let group = this.props.groupList[i]; let groupItem = (<li key={group.id}> <span data-id={group.id} onClick={this.onClickGroup.bind(this)}> {group.label}</span> <button data-id={group.id} className="group-edit-button" onClick={this.onClickGroupEdit.bind(this)}>編集</button> </li>); groupListDom.push(groupItem); } return groupListDom; } render() { return ( <div className="side-area"> <ul className="group-list"> {this.renderGroup()} </ul> <div className="side-area-footer"> <button className="add-group-button" onClick={this.onClickAddGroup.bind(this)}>グループ新規作成</button> </div> <AddGroupDialog show={this.state.showAddGroupDialog} onSave={this.onSaveAddGroupDialog.bind(this)} onCancel={this.onCancelAddGroupDialog.bind(this)} /> <EditGroupDialog show={this.state.showEditGroupDialog} group={this.state.selectedGroup} onSave={this.onSaveEditGroupDialog.bind(this)} onCancel={this.onCancelEditGroupDialog.bind(this)} onDelete={this.onDeleteEditGroupDialog.bind(this)} /> </div> ) } } //↓追記 const mapStateToProps = (state) => { return { groupList: state.groupList } } const mapDispatchToProps = (dispatch) => { return { onAddGroup: (data) => { dispatch(groupActions.addGroup(data)); } } } export default connect( mapStateToProps, mapDispatchToProps )(SideArea)

投稿2019/03/17 02:39

編集2019/03/17 02:47
alpaka

総合スコア170

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

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

y_aka

2019/03/17 03:31 編集

ありがとうございます。 Udemyのカリキュラムが各機能を徐々に移していく内容だったので こんがらせてしまったかもしれません。 頂いたコードを元にファイルの位置の関係で一部パス部分を修正しましたが 同様のエラーが出てしまいます。 container/sideArea.js ``` import React from "react"; import ReactDOM from "react-dom"; import AddGroupDialog from "../components/addGroupDialog"; import EditGroupDialog from "../components/editGroupDialog" //追記 import { connect } from "react-redux"; import { groupActions } from "../actions/groupActions"; // 文頭のexportを削除 class SideArea extends React.Component { constructor(props) { super(props); this.state = { showAddGroupDialog: false, showEditGroupDialog: false, selectedGroup: undefined } } onClickGroup(event) { let listItem = ReactDOM.findDOMNode(event.target); let id = listItem.dataset.id; this.props.onSelect(id); } onClickAddGroup(event) { this.setState({ showAddGroupDialog: true }); } onSaveAddGroupDialog(groupName) { console.log("onSaveAddGroupDialog", groupName); this.props.onAddGroup(groupName); this.setState({ showAddGroupDialog: false }); } onCancelAddGroupDialog() { this.setState({ showAddGroupDialog: false }); } onSaveEditGroupDialog(id, groupName) { this.props.onEditGroup(id, groupName); this.setState({ showEditGroupDialog: false }); } onCancelEditGroupDialog() { this.setState({ showEditGroupDialog: false }); } onDeleteEditGroupDialog(id) { this.props.onDeleteGroup(id); this.setState({ showEditGroupDialog: false }); } onClickGroupEdit(event) { let editButton = ReactDOM.findDOMNode(event.target); let id = editButton.dataset.id; let selectedGroup; for (let i = 0; i < this.props.groupList.length; i++) { if (this.props.groupList[i].id === id) { selectedGroup = this.props.groupList[i]; break; } } this.setState({ showEditGroupDialog: true, selectedGroup: selectedGroup }); } renderGroup() { let groupListDom = []; for (let i = 0; i < this.props.groupList.length; i++) { let group = this.props.groupList[i]; let groupItem = (<li key={group.id}> <span data-id={group.id} onClick={this.onClickGroup.bind(this)}> {group.label}</span> <button data-id={group.id} className="group-edit-button" onClick={this.onClickGroupEdit.bind(this)}>編集</button> </li>); groupListDom.push(groupItem); } return groupListDom; } render() { return ( <div className="side-area"> <ul className="group-list"> {this.renderGroup()} </ul> <div className="side-area-footer"> <button className="add-group-button" onClick={this.onClickAddGroup.bind(this)}>グループ新規作成</button> </div> <AddGroupDialog show={this.state.showAddGroupDialog} onSave={this.onSaveAddGroupDialog.bind(this)} onCancel={this.onCancelAddGroupDialog.bind(this)} /> <EditGroupDialog show={this.state.showEditGroupDialog} group={this.state.selectedGroup} onSave={this.onSaveEditGroupDialog.bind(this)} onCancel={this.onCancelEditGroupDialog.bind(this)} onDelete={this.onDeleteEditGroupDialog.bind(this)} /> </div> ) } } //↓追記 const mapStateToProps = (state) => { return { groupList: state.groupList } } const mapDispatchToProps = (dispatch) => { return { onAddGroup: (data) => { dispatch(groupActions.addGroup(data)); } } } export default connect( mapStateToProps, mapDispatchToProps )(SideArea) ``` ` bundle.js:30 TypeError: Cannot read property 'state' of undefined at Function.mapToProps (bundle.js:47) at r (bundle.js:47) at Function.r.mapToProps (bundle.js:47) at r (bundle.js:47) at bundle.js:47 at r.selectDerivedProps (bundle.js:47) at r.u.renderWrappedComponent (bundle.js:47) at r.u.indirectRenderWrappedComponent (bundle.js:47) at Ai (bundle.js:30) at qu (bundle.js:30) pu @ bundle.js:30 n.callback @ bundle.js:30 ou @ bundle.js:30 ru @ bundle.js:30 Bu @ bundle.js:30 Vu @ bundle.js:30 (anonymous) @ bundle.js:30 t.unstable_runWithPriority @ bundle.js:39 ja @ bundle.js:30 Na @ bundle.js:30 Pa @ bundle.js:30 ka @ bundle.js:30 Zu @ bundle.js:30 La @ bundle.js:30 Ma @ bundle.js:30 Wa.render @ bundle.js:30 (anonymous) @ bundle.js:30 Aa @ bundle.js:30 $a @ bundle.js:30 render @ bundle.js:30 (anonymous) @ bundle.js:47 n @ bundle.js:1 (anonymous) @ bundle.js:1 (anonymous) @ bundle.js:1 bundle.js:47 Uncaught TypeError: Cannot read property 'state' of undefined at Function.mapToProps (bundle.js:47) at r (bundle.js:47) at Function.r.mapToProps (bundle.js:47) at r (bundle.js:47) at bundle.js:47 at r.selectDerivedProps (bundle.js:47) at r.u.renderWrappedComponent (bundle.js:47) at r.u.indirectRenderWrappedComponent (bundle.js:47) at Ai (bundle.js:30) at qu (bundle.js:30) (anonymous) @ bundle.js:47 r @ bundle.js:47 r.mapToProps @ bundle.js:47 r @ bundle.js:47 (anonymous) @ bundle.js:47 r.selectDerivedProps @ bundle.js:47 u.renderWrappedComponent @ bundle.js:47 u.indirectRenderWrappedComponent @ bundle.js:47 Ai @ bundle.js:30 qu @ bundle.js:30 Hu @ bundle.js:30 Na @ bundle.js:30 Pa @ bundle.js:30 ka @ bundle.js:30 Zu @ bundle.js:30 La @ bundle.js:30 Ma @ bundle.js:30 Wa.render @ bundle.js:30 (anonymous) @ bundle.js:30 Aa @ bundle.js:30 $a @ bundle.js:30 render @ bundle.js:30 (anonymous) @ bundle.js:47 n @ bundle.js:1 (anonymous) @ bundle.js:1 (anonymous) @ bundle.js:1 `
alpaka

2019/03/17 04:16

そもそもUdemy動画内ではもともとのコードの状態でうごいて、自分も同じことをしたはずなのにエラーがでるんですか?それともいろいろ自分で組み合わせたためうごかなくなってしまったということですか?
y_aka

2019/03/17 04:18

カリキュラム通りにすすめていましたが動かなくなってしまいました。
alpaka

2019/03/17 04:30

動画では動いていて、自分の環境では動かない、ということですね。 であれば、カリキュラムを進める過程のどこかでUdemyでやっている環境と自分の環境に差異が生じてしまったということになります。 1.飛ばした手順が無いか 2.タイプミスがないか 3.バージョンはあっているか を確認する必要があるかなと思います。 なんなら一旦全部Udemyのコピペで動くかどうか確認してはいかがでしょう。それで動くなら、タイプミスやコードの抜けがあるということになります。 いずれにせよ、Udemyの講師に確認お願いします
y_aka

2019/03/17 04:42

分かりました。 一度上記を確認してみたいと思います!ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問