React/Redux - 无法读取未定义的属性"XXX"

dan*_*mcr 3 javascript mongodb node.js reactjs redux

这是我已经坚持了两个多星期的事情,所以这个问题是我最终解决这个问题的机会.我希望任何人都可以帮助我(因为问题很可能是小事/我错过了什么)


使用Node,Redux和React,我从Mongo数据库返回一个集合.我正在使用react-redux"connect"从我的商店中检索我的数据如下面的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>
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题:

因此,当我在我的JSX中返回"title"和"subTitle"时,它会完美地完成所有操作(见下文):

  <h1>{this.props.article.title}</h1>
  <h2>{this.props.article.subTitle}</h2>
Run Code Online (Sandbox Code Playgroud)

我的屏幕上也会显示数据(见下文):

在此输入图像描述

但是......一旦我补充:

  <h3>{this.props.article.body.section1.text}</h3>
Run Code Online (Sandbox Code Playgroud)

我的页面无法加载,我的控制台返回:

无法读取未定义的属性"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
                })
            })
    }
}
Run Code Online (Sandbox Code Playgroud)

减速器:

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
}
Run Code Online (Sandbox Code Playgroud)

商店:

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)
Run Code Online (Sandbox Code Playgroud)

节点/快速呼叫:

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

});
Run Code Online (Sandbox Code Playgroud)

我的mongo DB集合中的Record:

{
    "_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"
}
Run Code Online (Sandbox Code Playgroud)

对此问题的任何帮助或建议表示赞赏 - 谢谢你提前.

ric*_*ilv 5

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

然而,由于this.props.article最初是[],如果你尝试呈现this.props.article.body.section1.text,你的代码将抛出,因为同时观察到的异常article是一个对象,article.bodyundefined.已经抛出错误,当文章在商店中实际更新时,组件将无法重新呈现.

this.props.article在尝试渲染子键之前,您需要添加一个防护来检查形状,或者在请求返回实际文章之前为存储添加更完整的默认值.