React / Redux – 无法读取未定义的属性“XXX”

这是我一直坚持了两个多星期的事情,所以这个问题是我最后的机会。 我希望任何人都可以帮助我(因为问题很可能是小事/我错过了)


使用Node,Redux和React,我从Mongo数据库返回一个集合。 我正在使用react-redux“连接”从我的商店检索我的数据如在我的JSX下面看到的。

JSX:

import React from "react"; import {connect} from "react-redux" import {fetchArticle} from "../../actions/articleActions" var classNames = require('classnames'); import GlobalHero from '../modules/GlobalHero.jsx'; @connect((store) => { return {article: store.article.article, fetching: store.article.fetching}; }) export default class Article extends React.Component { // BEFORE COMPONENT RENDER (For Everyhing else) constructor() { super(); //sets initial state this.state = { page: "Article" }; } // BEFORE COMPONENT RENDER (For Ajax / Dispatcher Events): get article Title / Thumbnail rows based on this.props.indexLimit componentWillMount = () => { console.log(this.props) this.props.dispatch(fetchArticle(this.props.params.id)) } // ON COMPONENT RENDER componentDidMount = () => {} render() { if (this.props.fetching) { return ( <p>Loading...</p> ); } else { return ( <div> <h1>{this.props.article.title}</h1> <h2>{this.props.article.subTitle}</h2> </div> ); } } } 

我的问题:

所以当我在我的JSX中返回“title”和“subTitle”时,它将所有的东西都完美地取出来(见下面):

  <h1>{this.props.article.title}</h1> <h2>{this.props.article.subTitle}</h2> 

数据也可以在我的屏幕上看到(见下文):

在这里输入图像描述

但是,只要我补充说:

  <h3>{this.props.article.body.section1.text}</h3> 

我的页面不会加载,我的控制台返回:

无法读取未定义的属性'section1'

当我在控制台中查看返回的数据的状态时:

在这里输入图像描述

正如你所看到的,它在控制台中返回'section1',所以我必须在我的JSX中调用我的'section1'错误?

我在想,这个问题可能是因为'section1'嵌套在我的mongo db集合中,而不是'title'或'subTitle'。

下面我会告诉你我的这个网页的其余路线 – 我已经看了无尽的在线,不能指出我的问题。

行动:

 import axios from "axios"; //var resourceUrl = "http://localhost:7777/api/schools"; export function fetchArticle(id) { return function(dispatch) { dispatch({ type: "FETCH_ARTICLE" }) axios.get('/api/article', { params: { id: id } }) .then((response) => { dispatch({ type: "FETCH_ARTICLE_FULFILLED", payload: response.data }) }) .catch((err) => { dispatch({ type: "FETCH_ARTICLE_REJECTED", payload: err }) }) } } 

减速器:

 export default function reducer(state = { article: [], fetching: false, fetched: false, error: null, }, action) { switch (action.type) { case "FETCH_ARTICLE": { return { ...state, fetching: true } } case "FETCH_ARTICLE_REJECTED": { return { ...state, fetching: false, error: action.payload } } case "FETCH_ARTICLE_FULFILLED": { return { ...state, fetching: false, fetched: true, article: action.payload, } } } return state } 

商店:

 import { applyMiddleware, createStore } from "redux" import logger from "redux-logger" import thunk from "redux-thunk" import promise from "redux-promise-middleware" import reducer from "./reducers" const middleware = applyMiddleware(promise(), thunk, logger()) export default createStore(reducer, middleware) 

节点/快速呼叫:

 app.get('/api/article', (req, res) => { var ObjectId = require('mongodb').ObjectID; var articles; db.collection('articles') .findOne({ "_id": ObjectId("58c2a5bdf36d281631b3714a") }) .then(result => { articles = result; }).then(() => { res.send(articles); }).catch(e => { console.error(e); }); }); 

logging在我的mongo DB集合中:

 { "_id": { "$oid": "58c2a5bdf36d281631b3714a" }, "title": "EntertheBadJah", "subTitle": "Lorem ipsum dolor", "thmbNailImg": "", "headerImg": "", "body": { "section1": { "include": true, "text": "Lorem ipsum dolor sit amet, dico posse integre cum ut, praesent iudicabit tincidunt te sea, ea populo semper laoreet duo." }, "section2": { "include": true, "text": "Lorem ipsum dolor sit amet, dico posse integre cum ut, praesent iudicabit tincidunt te sea, ea populo semper laoreet duo." }, "bodyImg": { "include": true, "img": "" }, "section3": { "include": true, "text": "Lorem ipsum dolor sit amet, dico posse integre cum ut, praesent iudicabit tincidunt te sea, ea populo semper laoreet duo." } }, "links": { "recourse": { "include": false, "text": "Go watch their interview", "link": "" }, "soundcloud": { "include": true, "link": "www.soundcloud.com/BadJah" }, "spotify": { "include": false, "link": "" }, "youtube": { "include": false, "link": "" }, "twitter": { "include": false, "link": "" }, "facebook": { "include": false, "link": "" }, "instagram": { "include": false, "link": "" } }, "keywords": "Badjah", "date": "", "author": "Aagentah", "dateAdded": "2017-06-01T00:00:00.000Z" } 

任何关于这个问题的帮助或build议表示赞赏 – 预先感谢您。

当它的道具(通过Redux连接提供)改变时,React将重新渲染页面。 由于您只是触发请求来获取componentWillMount的数据,根据定义,这将不会在第一个渲染完成。 然而,这在第一种情况下没有问题,因为this.props.article保证是一个对象,所以this.props.article.title只是undefined 。 一旦对API的请求返回, article就会在商店中更新,并且页面呈现预期的内容。

但是,因为this.props.article最初是[] ,所以如果您尝试渲染this.props.article.body.section1.text ,那么您的代码将会抛出一个exception,因为虽然article是一个对象,但article.bodyundefined 。 在已经引发错误的情况下,组件将在商店中实际更新的商品时失败。

在尝试呈现子this.props.article之前,您需要添加一个警卫来检查this.props.article的形状,或者在请求返回实际文章之前,为商店添加更完整的默认值。

尝试这样的事情。 可能是在第一个渲染循环中它还没有出现。

 checkRender(){ typeof this.props.article.body === 'undefined' ? return null : return this.props.article.body.section1.text } 

然后使用它::>

 <h3>{checkRender}</h3> 

我可以肯定的build议添加streamtypes检查到您的代码库( http://flow.org )。 它可以添加在每个文件的基础上,但可以显着帮助debugging这些types的问题。