現在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> ) } }