无法访问 React 中对象或数组中的特定键
更新 我可以在 render() 函数的 return 语句中正常访问所有内容。例如 user.exercises[0].exercise.name 输出“squats”。这就是为什么更令人困惑的是为什么我无法在 return 语句之前访问它以创建将值映射到表的函数。 更新
我似乎在访问 React 中的特定键时遇到问题。我尝试读取的对象是从 mongodb 的后端 API 请求的,并以 JSON 形式输出。我已经尝试过通过 lodash 将对象映射到数组后访问它,但问题是一样的。我可能只是错误地读取了对象并指定了错误的键,但我看不到它。我对 console.logging 整个 JSON 或顶部键(例如“name”或“age”)没有任何问题,方法是编写 {user.name},但任何更深层次的内容都会崩溃。这是 JSON:
{
"_id": "592ab4523a4d39085fe4c1d9",
"nickname": "mmsmsy",
"name": "Mateusz",
"gender": "male",
"age": 26,
"exercises": [
{
"exercise": {
"name": "squats",
"records": []
}
},
{
"exercise": {
"name": "legpresses",
"records": []
}
},
{
"exercise": {
"name": "deadlifts",
"records": []
}
},
{
"exercise": {
"name": "benchpresses",
"records": []
}
},
{
"exercise": {
"name": "pullups",
"records": []
}
},
{
"exercise": {
"name": "shoulderpresses",
"records": []
}
},
{
"exercise": {
"name": "curls",
"records": []
}
}
]
}
以及 React 代码:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import _ from 'lodash';
class UserDetails extends Component{
constructor(props) {
super(props)
this.state = {
user: null,
loading: false
}
}
componentDidMount() {
this.setState({
loading: true
});
axios.get(`http://192.168.0.248:3001/api/v1/users/${this.props.match.params.id}`)
.then(res => res.data)
.then(user => {
this.setState({
user: user,
loading: false
});
});
}
render() {
const {loading, user} = this.state;
let userInfo = _.map(user, (value, prop) => {
return { "prop": prop, "value": value };
});
console.log(user, userInfo);
if (loading || !user) {
return (
<p className="user-loading">Loading ...</p>
);
}
return (
<div id="user-details">
<div className="nav">
<Link className="nav-back-to-list" to="/">Back to the list</Link>
</div>
<div id="user-details-icon">
<img src={`/images/user_${user.gender}.png`} alt={`generic user ${user.gender} icon`} />
</div>
<table>
<tbody><tr><td>Nickname</td><td>{user.nickname}</td></tr></tbody>
<tbody><tr><td>Name</td><td>{user.name}</td></tr></tbody>
<tbody><tr><td>Gender</td><td>{user.gender}</td></tr></tbody>
<tbody><tr><td>Age</td><td>{user.age}</td></tr></tbody>
</table>
<h1>Records</h1>
</div>
)
}
}
export default UserDetails;
这是我使用 console.log(user); 获得的结果,没有错误
Object {_id: "592ab4523a4d39085fe4c1d9", nickname: "mmsmsy", name: "Mateusz", gender: "male", age: 26…}age: 26exercises: Array(7)0: Objectexercise: Objectname: "squats"records: Array(0)length: 0__proto__: Array(0)__proto__: Objectconstructor: function Object()hasOwnProperty: function hasOwnProperty()isPrototypeOf: function isPrototypeOf()propertyIsEnumerable: function propertyIsEnumerable()toLocaleString: function toLocaleString()toString: function toString()valueOf: function valueOf()__defineGetter__: function __defineGetter__()__defineSetter__: function __defineSetter__()__lookupGetter__: function __lookupGetter__()__lookupSetter__: function __lookupSetter__()get __proto__: function __proto__()set __proto__: function __proto__()__proto__: Object1: Objectexercise: Object__proto__: Object2: Object3: Object4: Object5: Object6: Objectlength: 7__proto__: Array(0)gender: "male"name: "Mateusz"nickname: "mmsmsy"_id: "592ab4523a4d39085fe4c1d9"__proto__: Object
这是使用 lodash 将其转换为数组 console.log(userInfo);
(6) [Object, Object, Object, Object, Object, Object]
现在,示例和如果我尝试访问 f.e 时得到的错误: console.log(user.exercises[0].exercise.name);
Uncaught TypeError: Cannot read property 'exercises' of null
at UserDetails.render (UserDetails.js:33)
at ReactCompositeComponent.js:796
at measureLifeCyclePerf (ReactCompositeComponent.js:75)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:795)
at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:822)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:362)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:238)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:697)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:516)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at mountComponentIntoNode (ReactMount.js:104)
at ReactReconcileTransaction.perform (Transaction.js:140)
at batchedMountComponentIntoNode (ReactMount.js:126)
at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:140)
at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
at Object.batchedUpdates (ReactUpdates.js:97)
at Object._renderNewRootComponent (ReactMount.js:320)
at Object._renderSubtreeIntoContainer (ReactMount.js:401)
at Object.render (ReactMount.js:422)
at Object.<anonymous> (index.js:10)
at __webpack_require__ (bootstrap 9a6d4f1…:657)
at fn (bootstrap 9a6d4f1…:85)
at Object.<anonymous> (fetch.js:461)
at __webpack_require__ (bootstrap 9a6d4f1…:657)
at validateFormat (bootstrap 9a6d4f1…:706)
at bundle.js:710
render @ UserDetails.js:33
(anonymous) @ ReactCompositeComponent.js:796
measureLifeCyclePerf @ ReactCompositeComponent.js:75
_renderValidatedComponentWithoutOwnerOrContext @ ReactCompositeComponent.js:795
_renderValidatedComponent @ ReactCompositeComponent.js:822
performInitialMount @ ReactCompositeComponent.js:362
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
mountChildren @ ReactMultiChild.js:238
_createInitialChildren @ ReactDOMComponent.js:697
mountComponent @ ReactDOMComponent.js:516
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
performInitialMount @ ReactCompositeComponent.js:371
mountComponent @ ReactCompositeComponent.js:258
mountComponent @ ReactReconciler.js:46
mountComponentIntoNode @ ReactMount.js:104
perform @ Transaction.js:140
batchedMountComponentIntoNode @ ReactMount.js:126
perform @ Transaction.js:140
batchedUpdates @ ReactDefaultBatchingStrategy.js:62
batchedUpdates @ ReactUpdates.js:97
_renderNewRootComponent @ ReactMount.js:320
_renderSubtreeIntoContainer @ ReactMount.js:401
render @ ReactMount.js:422
(anonymous) @ index.js:10
__webpack_require__ @ bootstrap 9a6d4f1…:657
fn @ bootstrap 9a6d4f1…:85
(anonymous) @ fetch.js:461
__webpack_require__ @ bootstrap 9a6d4f1…:657
validateFormat @ bootstrap 9a6d4f1…:706
(anonymous) @ bundle.js:710
问题是您已将初始状态用户指定为空,并且当您记录
user.exercises[0]
时,它会抛出该错误,因为当应用程序第一次呈现时 API 的结果尚未准备好。
在 console.log() 之前执行检查
class UserDetails extends Component{
constructor(props) {
super(props)
this.state = {
user: null,
loading: false
}
}
componentDidMount() {
this.setState({
loading: true
});
axios.get(`http://192.168.0.248:3001/api/v1/users/${this.props.match.params.id}`)
.then(res => res.data)
.then(user => {
this.setState({
user: user,
loading: false
});
});
}
render() {
const {loading, user} = this.state;
if(user != null) {
let userInfo = _.map(user, (value, prop) => {
return { "prop": prop, "value": value };
});
console.log(user.exercises[0].exercise, userInfo);
}
if (loading || !user) {
return (
<p className="user-loading">Loading ...</p>
);
}
return (
<div id="user-details">
<div className="nav">
<Link className="nav-back-to-list" to="/">Back to the list</Link>
</div>
<div id="user-details-icon">
<img src={`/images/user_${user.gender}.png`} alt={`generic user ${user.gender} icon`} />
</div>
<table>
<tbody><tr><td>Nickname</td><td>{user.nickname}</td></tr></tbody>
<tbody><tr><td>Name</td><td>{user.name}</td></tr></tbody>
<tbody><tr><td>Gender</td><td>{user.gender}</td></tr></tbody>
<tbody><tr><td>Age</td><td>{user.age}</td></tr></tbody>
</table>
<h1>Records</h1>
</div>
)
}
}
尝试将您的 axios 请求移至
componentWillMount() { ... } } 生命周期方法。
您可能在
axios
get 调用后没有获取到 React 组件实例
“this”
,请尝试以下操作:
componentDidMount() {
this.setState({
loading: true
});
let _this = this;
axios.get(`http://192.168.0.248:3001/api/v1/users/${this.props.match.params.id}`)
.then(res => res.data)
.then(user => {
_this.setState({
user: user,
loading: false
});
});
}