2017-05-28 46 views
0

UPDATE我可以在render()函數的return語句中正常訪問所有內容。 F.e user.exercises [0] .exercise.name輸出「蹲」。這就是爲什麼我更難以理解爲什麼在return語句之前我無法訪問它以創建一個將值映射到表的函數。 UPDATE無法訪問React對象或數組中的特定鍵

我似乎有訪問React中特定鍵的問題。我嘗試讀取的對象是從mongodb的後端API請求的,並以JSON格式輸出。我已經嘗試通過lodash將對象映射到數組後訪問它,但問題是相同的。我可能只是讀對象錯誤並指定了錯誤的鍵,但我看不到它。我沒有任何問題console.logging整個JSON或頂部鍵,通過寫{user.name} f.e「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": [] 
     } 
     } 
    ] 
    } 

而且陣營代碼:

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(用戶);

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 

回答

0

嘗試將您的axios請求移至componentWillMount() { ... }生命週期方法。

+0

不幸的是沒有改變。 –

+0

並設置'user'作爲axios調用的響應'然後(res => {this.setState({user:res.data,loading:false});}' –

+0

我不知道我是否理解你我認爲你沒有從axios請求中得到任何正確的數據,但是我和我在記錄整個響應時沒有任何問題,但是當試圖訪問練習中的值時,我一直在錯誤我更新了記錄整個信息和userInfo變量時獲得的數據的問題 –

0

也許你沒有得到反應組件實例「這個」axios get調用,試試這個:

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 
     }); 
     }); 
    } 
+0

我不知道我是否明白你的建議是正確的,但我相信你認爲我沒有得到任何正確的但是我確實沒有記錄整個響應的任何問題,但是當嘗試訪問練習中的值時,我總是收到錯誤信息,並且使用記錄整個信息時獲得的數據更新了問題, userInfo變量。 –

+0

@MateuszMysiak I無法讀取您的React Code中的'Exercises'。 – Arpit

+0

的確,這就是問題所在。每次嘗試時,我都會得到錯誤練習爲空。也許這是數據結構中的問題?不過,我基本上覆制了pokeapi.co/api/v2/pokemon/1示例。 –

1

問題是,你已分配的初始狀態的用戶爲空,當您登錄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> 
    ) 
    } 
} 
+0

它的行爲完全一樣。問題不在於用戶值本身是空的,因爲axios將它從componentDidMount中的後端設置爲JSON,並且對console.log(user)沒有任何問題。唯一的問題是當我嘗試記錄更深的用戶,如user.exercises [0]或user.exercises [0] .exercise或user.exercise [0] .exercise.name。基本上任何練習的關鍵。 –

0

確定。因此,在通過不同類型的數組循環/映射後,我終於找到了一個解決方案,並希望與任何可能會遇到這個愚蠢問題的人分享。

基本上,Shubham Khatri是正確的建議做一個空檢查(是否存在一個值)。但是,它是在錯誤的鍵上完成的。由於我的數據庫中總是有一些用戶,所以我們不需要對它執行空檢查。我需要做的是對「exercices」數組內的「records」數組進行空值檢查。並非所有用戶都提交了結果,因此在循環/映射時沒有數據可以執行操作。在添加檢查之後,如果每個用戶中有任何記錄,則該應用可以正常顯示那些具有這些記錄的用戶的結果,並顯示沒有發佈任何結果的「沒有結果顯示」。

我最近了解到,學習API是需要哪些密鑰的好習慣,這樣我們就不必對它們執行空檢查,也不需要哪些密鑰,並且可能會缺少一些密鑰結果,我們應該絕對做空檢查。或者,如果我們建立自己的API,我們應該指定自己,哪些將在每個對象中出現,哪些是可選的。

相關問題