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) displayPosts () {
//console.log(post) works, console.log(post.title) returns undefined.
return _.map(this.props.posts, (post)=>{return <div>post.title</div>;});
}
但是如果我尝试console.log(post.title),我会得到未定义的。
同样,如果我尝试做类似的事情:
select *
from TableABC
where TableABC.label_id is null
union all
select *
from TableABC
join Labels
on TableABC.label_id = Lables.id
and Lablestype = '123'
我一无所获。
在这里你可以看到console.log()的结果。 前者来自史诗,后者来自组成部分。
这里有我打开的回购链接的链接: https://github.com/Deviad/redux-router-playground
答案 0 :(得分:4)
问题实际上在你的reducer中(从你的链接回购中找到):
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;
}
};
action.payload
已经是一个数组,但是你把它放在另一个数组中,所以是一个数组数组。因此,当您映射this.props.posts
时,您只得到1个结果,即实际的帖子数组。当你记录时,你可能只是没注意到。
// THIS IS THE PROBLEM:
return [
...state,
action.payload
];
相反,你可以按原样返回数组:
return action.payload;
虽然上述解决方案是IMO可接受的(并且说实话,运输代码是第一优先级),但这实际上仍然不是使用redux的最惯用的方式。相反,将redux视为数据库。你如何在数据库中存储(也正常化)这些?如果您回答“按ID编制索引”,那么您是对的!
所以你的redux状态看起来像这样:
{
posts: {
'123': {
id: '123',
title: 'first title'
},
'456': {
id: '456',
title: 'second title'
}
}
}
这是你可以做到的一种方式:
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;
}
};
因为这种情况的变化很常见,很多时候是嵌套的,有些人会选择使用normalizr库:
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
因为在您的情况下,您需要将它们作为该UI容器中的帖子数组返回,它也具有用于非规范化的实用程序,或者如果支持,您可以使用Object.values
执行此操作:
function mapStateToProps(state) {
return {
posts: Object.values(state.posts)
};
}
normalize()
调用还会返回一个ID数组,您可能会发现它们可以在某个地方存储在redux中,或者您可以在需要时按需使用Object.keys(state.posts)
- 这就是我所说的因为它可以防止同步问题,但如果项目数量很大,那么对于性能原因并不总是可行的。这是一个我担心的问题。
你可能想知道为什么我们会在那个问题上再次对它进行反规范化呢?完整的答案是长篇大论,但简短的要点是一致性,未来状态更新的简易性,以及后续视图的快速“发布ID”查找。这是使redux变得更好的一个主要部分,否则它变成了一个时间旅行的美化吸气剂/定位器,它几乎不值得借助它。
这在redux文档的Normalizing State Shape部分进行了讨论。