Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs Redux Observable、React、componentDidMount从API获取无法从对象获取属性_Reactjs_Redux_Rxjs_Redux Observable - Fatal编程技术网

Reactjs Redux Observable、React、componentDidMount从API获取无法从对象获取属性

Reactjs Redux Observable、React、componentDidMount从API获取无法从对象获取属性,reactjs,redux,rxjs,redux-observable,Reactjs,Redux,Rxjs,Redux Observable,但是如果我尝试console.log(post.title),我会得到未定义的 同样,如果我尝试做以下事情: displayPosts () { //console.log(post) works, console.log(post.title) returns undefined. return _.map(this.props.posts, (post)=>{debugger;console.log(post.title);}); }

但是如果我尝试console.log(post.title),我会得到未定义的

同样,如果我尝试做以下事情:

    displayPosts () {
        //console.log(post) works, console.log(post.title) returns undefined.
        return  _.map(this.props.posts, (post)=>{debugger;console.log(post.title);});
    }
displayPosts(){
//log(post)工作,console.log(post.title)返回未定义的。
return uu.map(this.props.posts,(post)=>{return post.title;});
}
我没有得到任何回报

在这里,您可以看到console.log()的结果。 前者来源于史诗,后者来源于组件

这里有一个指向我打开的回购协议的链接:

问题实际上在于您的减速机(从链接回购中找到):

action.payload
已经是一个数组,但是您将它放在另一个数组中,因此是一个数组数组。因此,当您映射到
this.props.posts
时,您只会得到一个结果,即实际的posts数组。当你登录时,你可能只是没有注意到

export default function postsReducer(state=[], action) {
    switch (action.type) {
        case ActionTypes.FETCH_POSTS_FULLFILLED:
            // THIS IS THE PROBLEM:
            return [
                ...state,
                action.payload
            ];

        default:
            return state;
    }
};
相反,您可以按原样返回数组:

// THIS IS THE PROBLEM:
return [
    ...state,
    action.payload
];

虽然上面的解决方案是IMO可以接受的(老实说,装运代码是#1优先级),但这实际上仍然不是使用redux的最惯用方法。相反,可以将redux视为一个数据库。您将如何在数据库中存储(也称为规范化)这些数据?如果你回答“按ID索引”,你是对的

因此,您的redux状态可能如下所示:

return action.payload;
这里有一种方法可以做到这一点:

{
    posts: {
        '123': {
            id: '123',
            title: 'first title'
        },
        '456': {
            id: '456',
            title: 'second title'
        }
    }
}
因为这种变体很常见,很多时候是嵌套的,所以有些人会选择使用normalizer库:

export default function postsReducer(state = {}, action) {
    switch (action.type) {
        case ActionTypes.FETCH_POSTS_FULLFILLED:
            return action.payload.reduce((acc, post) => {
                acc[post.id] = post;
                return acc;
            }, { ...state });
            // use Object.assign if object-spread
            // syntax isn't supported

        default:
            return state;
    }
};
因为在您的情况下,您需要将它们作为该UI容器中的一个POST数组返回,所以它还具有用于反规范化的实用程序,或者您可以使用
对象执行此操作。如果支持,则值为:

import { normalize, schema } from 'normalizr';

const postSchema = new schema.Entity('posts');

export default function postsReducer(state = {}, action) {
    switch (action.type) {
        case ActionTypes.FETCH_POSTS_FULLFILLED:
            // use Object.assign if object-spread
            // syntax isn't supported
            return {
                ...state,
                ...normalize(action.payload, [postSchema]).entities.posts
            };
// etc
调用
normalize(),但是,如果项目数量很大,出于性能原因,这并不总是可行的。这是一个我会担心的问题

你可能想知道,如果我们只是想再次去规范化它,为什么我们会遇到这样的麻烦;完整的答案是冗长的,但简短的要点是一致性、未来状态更新的方便性,以及以后视图的快速“按ID发布”查找。这是redux之所以伟大的一个主要原因,否则它主要会成为一个时间旅行的荣耀的getter/setter,而这几乎不值得做样板


这在redux文档的一节中进行了讨论。

问题实际上在于您的减速机(从链接的回购中找到):

action.payload
已经是一个数组,但是您将它放在另一个数组中,因此是一个数组数组。因此,当您映射到
this.props.posts
时,您只会得到一个结果,即实际的posts数组。当你登录时,你可能只是没有注意到

export default function postsReducer(state=[], action) {
    switch (action.type) {
        case ActionTypes.FETCH_POSTS_FULLFILLED:
            // THIS IS THE PROBLEM:
            return [
                ...state,
                action.payload
            ];

        default:
            return state;
    }
};
相反,您可以按原样返回数组:

// THIS IS THE PROBLEM:
return [
    ...state,
    action.payload
];

虽然上面的解决方案是IMO可以接受的(老实说,装运代码是#1优先级),但这实际上仍然不是使用redux的最惯用方法。相反,可以将redux视为一个数据库。您将如何在数据库中存储(也称为规范化)这些数据?如果你回答“按ID索引”,你是对的

因此,您的redux状态可能如下所示:

return action.payload;
这里有一种方法可以做到这一点:

{
    posts: {
        '123': {
            id: '123',
            title: 'first title'
        },
        '456': {
            id: '456',
            title: 'second title'
        }
    }
}
因为这种变体很常见,很多时候是嵌套的,所以有些人会选择使用normalizer库:

export default function postsReducer(state = {}, action) {
    switch (action.type) {
        case ActionTypes.FETCH_POSTS_FULLFILLED:
            return action.payload.reduce((acc, post) => {
                acc[post.id] = post;
                return acc;
            }, { ...state });
            // use Object.assign if object-spread
            // syntax isn't supported

        default:
            return state;
    }
};
因为在您的情况下,您需要将它们作为该UI容器中的一个POST数组返回,所以它还具有用于反规范化的实用程序,或者您可以使用
对象执行此操作。如果支持,则值为:

import { normalize, schema } from 'normalizr';

const postSchema = new schema.Entity('posts');

export default function postsReducer(state = {}, action) {
    switch (action.type) {
        case ActionTypes.FETCH_POSTS_FULLFILLED:
            // use Object.assign if object-spread
            // syntax isn't supported
            return {
                ...state,
                ...normalize(action.payload, [postSchema]).entities.posts
            };
// etc
调用
normalize(),但是,如果项目数量很大,出于性能原因,这并不总是可行的。这是一个我会担心的问题

你可能想知道,如果我们只是想再次去规范化它,为什么我们会遇到这样的麻烦;完整的答案是冗长的,但简短的要点是一致性、未来状态更新的方便性,以及以后视图的快速“按ID发布”查找。这是redux之所以伟大的一个主要原因,否则它主要会成为一个时间旅行的荣耀的getter/setter,而这几乎不值得做样板


这在redux文档的一节中进行了讨论。

@jayhelp谢谢。您澄清了我不清楚的地方,并提供了使用lodash中的u.mapKeys()的极好替代方法。@jayhelps,考虑到我与您的答案的整合,哪种方法是迭代iterable结构的最佳方法?我这样问是因为在某些语言中,考虑到性能问题,foreach和其他一些map更好。例如,在PHP中,foreach可能比5.6上的map性能更好。在其他语言中,它是更好的地图。看起来最好的选择是第一个。性能方面,在一小部分数据上,它们在同一时间执行相同的任务:在本例中为7/10秒。从内存消耗的角度来看,使用Array.prototype.slice.call()的后者已经占用了10 MB的内存,同时还有一个不需要复制到变量中的解决方案:displayPosts(){return Object.values(this.props.posts).map((post)=>{return return({post.title})!后续问题应作为新的堆栈溢出问题提出。@jayhelps谢谢。您澄清了我不清楚的地方,并提供了一个很好的替代方案,以取代使用lodash中的u.mapKeys()。@jayhelps,考虑到我对您的答案的整合,哪一个是最佳答案