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

标签 javascript node.js mongodb reactjs redux

这是我已经坚持了 2 周多的问题,所以这个问题是我解决这个问题的最后机会。我希望任何人都可以帮助我(因为问题很可能是小事/我错过的事)


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

我的问题:

所以当我在我的 JSX 中返回“title”和“subTitle”时,它会完美地处理所有内容(见下文):

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

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

enter image description here

但是...一旦我添加:

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

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

Cannot read property 'section1' of undefined

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

enter image description here

如您所见,它在控制台中返回“section1”,所以我一定是在我的 JSX 中调用了“section1”错误?

我认为问题可能与“section1”比“title”或“subTitle”嵌套在我的 mongo 数据库集合中更深这一事实有关。

下面我将向您展示此页面的其余路线 - 我在网上看了没完没了,但无法确定我的问题。

Action :

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

reducer :

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)

Node/快速调用:

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

});

我的 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"
}

如有任何关于此问题的帮助或建议,我们将不胜感激 - 提前致谢。

最佳答案

当 props(通过 Redux connect 提供)改变时,React 将重新渲染页面。由于您只是在 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 的形状,或者在请求返回实际值之前向存储添加更完整的默认值文章。

关于javascript - React/Redux - 无法读取未定义的属性 "XXX",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43323928/

相关文章:

javascript - AngularJS 如何从返回值中找到正确的属性

mongodb - Mongoose/MongoDB 在保存时抛出重复键错误?

node.js - Windows10 - fatal error : Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

javascript - 如何将数据推送到 MongoDB 中的现有文档中?

javascript - 如何使用 Mongoose 从集合中删除所有文档?

javascript - 在传单 map 上捕获 d3 中的鼠标悬停

Javascript (JQuery) 变量覆盖问题

javascript - 在 JavaScript 中从数组到序列

angularjs - 总是在后台运行 Gulp

javascript - LetsEncrypt 覆盖不同端口