Reactjs Redux Observable、React、componentDidMount从API获取无法从对象获取属性
但是如果我尝试console.log(post.title),我会得到未定义的 同样,如果我尝试做以下事情: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);}); }
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,考虑到我对您的答案的整合,哪一个是最佳答案