TypeError:无法读取未定义的属性“map”并四处走走
有一个如下所示定义的对象 contactBook。我将其发送到 redux 并以完全相同的格式返回。
{“Book1” : [{name: “Bob”},{name, “Jane”}, {name, “Mary”]}
我打算将其转移到名称列表
import React, {Component} from 'react'
import {bindActionCreators} from "redux";
import * as actions from "../redux/actions";
import {withRouter} from 'react-router'
import {connect} from 'react-redux'
class ListContactComponent extends Component {
constructor(props) {
super(props);
this.state = {
message: null
};
}
componentDidMount() {
this.props.startLoadingContacts(this.props.match.params.bookName);
}
addContactClicked = () => {
this.props.history.push({
pathname: `/addressBook/contact/`,
state: this.state.bookName
})
};
render() {
let contacts = Object.values(this.props.contacts).flat();
return (
<div className="container">
<h3>All Contacts</h3>
{this.state.message && <div class="alert alert-success">{this.state.message}</div>}
<div className="container">
<table className="table">
<thead>
<tr>
<th>Name</th>
<th>Phone Number</th>
</tr>
</thead>
<tbody>
{
contacts.map(
(contact, index) =>
<tr key={index}>
<td>{contact.name}</td>
<td>{contact.phoneNumber}</td>
</tr>
)
}
</tbody>
</table>
<div className="row">
<button className="btn btn-success" onClick={this.addContactClicked}>Add</button>
</div>
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
contacts: state.contacts
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(actions, dispatch)
}
const connectedContactList = withRouter(connect(mapStateToProps, mapDispatchToProps)(ListContactComponent));
export {connectedContactList as ListContactComponent};
-
如果我使用:
contacts = contactsBook[Book1]
我收到 TypeError:无法读取未定义的属性“map”
此错误的原因是什么,如何修复?
如果我不使用 redux 返回的对象,它就可以正常工作。我真的不知道有什么区别?
Actions:
export function startLoadingContacts(addressBookName) {
return (dispatch) => {
return AddressBookDataService
.retrieveContacts(addressBookName)
.then(
(response) => {
let contacts = {};
contacts[addressBookName] = response.data;
dispatch(loadContacts(contacts))
}).catch((error) => {
console.log(error)
})
}
}
export function loadContacts(contacts) {
return {
type: 'LOAD_CONTACTS',
contacts
}
}
Reducer:
function contacts(state = {}, action) {
switch (action.type) {
case 'ADD_CONTACT':
return "....";
case 'LOAD_CONTACTS':
return action.contacts;
default:
return state
}
}
-
控制台日志:
contactsBook: {Book1: Array(3)} Book1: Array(3) 0: {name: "Bob"} 1: {name: "Jane"} 2: {name: "Mary"} length: 3 __proto__: Array(0) __proto__: Object contacts: (3) [{…}, {…}, {…}] 0: {name: "Bob"} 1: {name: "Jane"} 2:{name:"Mary"} 长度:3
或
-
如果我使用:
contacts = Object.values(contactsBook)
, 则没有输出。
控制台日志:
[Array(3)] 0:Array(3) 0:{name:"Bob"} 1:{name:"Jane"} 2:{name:"Mary"} 长度:3 __proto__:Array(0) 长度:1
-
如果我使用:
使用 JSON.stringy(contacts) 时
它会打印:
[[ {name:"Bob"},..]] 而不是[{name: "Bob"},.. ]
这种情况下,如何去掉外面的 []?
如果模拟一个数据扭曲器 =[[data]],我可以通过扭曲器[0]去除外层。
但是它不适用于
contacts = Object.values(contactsBook)
contacts[0]
最后 flat() 解决了这个问题
contacts = Object.values(contactsBook).flat()
你能帮忙解释一下原因吗?
如果我不得不猜测,您需要向 Reducer 添加初始状态,该状态不是空对象,例如空数组
[]
。这样,当组件首次呈现并连接到 redux 时,它将具有一个有效的定义值,可以进行映射。
编辑
好的,您的状态形状
是
{[book: string]: string[]>
。在这种情况下,Reducer 的初始状态 (
{
)
没问题
,您
确实
需要从路由参数中获取图书名称。在这里,我更新了
mapStateToProps
函数,以便同时引入组件自己的 props,并进行计算以将
contactList
作为 prop 返回给组件。
/edit
Reducer
const initialState = {};
function contacts(state = initialState, action) {
switch (action.type) {
case 'ADD_CONTACT':
return "....";
case 'LOAD_CONTACTS':
return action.contacts;
default:
return state
}
}
Component
const { contactList } = this.props;
...
contactList.map(...
...
function mapStateToProps(state, ownProps) {
const { match: { params: { bookName } } = ownProps;
return {
contactList: state.contacts[bookName] || [],
}
}
替代解决方案 Guard Pattern
{
contacts && contacts.map(
(contact, index) => (
<tr key={index}>
<td>{contact.name}</td>
<td>{contact.phoneNumber}</td>
</tr>
))
}
将你的 map 函数更改为:
{contacts["Book1"].map((contact, index) => (
<tr key={index}>
<td>{contact.name}</td>
<td>{contact.phoneNumber}</td>
</tr>
))}