我试图过滤并显示其帖子ID为'与当前帖子ID匹配。我使用Redux/Reselect
,它可以正常工作,但有时会返回错误,指出post._id
未定义/ null ..
以下是代码:
const getAllComments = state => state.comments.comments;
const getPost = state => state.posts.post;
export const getCommentsByPostID = createSelector([ getAllComments, getPost ], (comments, post) => {
return comments.filter((c) => c.postID == post._id);
})
我在getComments()
之后在componentDidMount
内呼叫getPost(params.id)
。
如何确定帖子是否已定义?我应该调用in render方法吗?
答案 0 :(得分:1)
因此,在调用选择器之前,必须确保您的数据(posts
和comments
)已被提取并可供您使用。
您可以尝试以下流程,以后再尝试(如果适用),可以对其进行改进:
对于每个实体(Post
,Comment
等),您将保留一个名为fetching
的新元属性。使用此属性,您将始终知道数据的当前状态。同样,这将防止您对同一资源进行多个API调用(假设您有两个组件,这些组件需要并获取帖子,因此仅应调用1个API请求)。它将具有三个可能的值:
not-started
-数据未启动,没有触发数据获取请求。fetching
-正在获取数据。fetched
-数据已被提取。在componentDidMount
中,您将调用API调用(动作创建者),这将分别更改fetching
状态。
mapStateToProps
中,只有在获取数据的情况下,您才会调用选择器,诸如此类:const isFetching = entity => ['not-started', 'fetching'].includes(entity.fetching)
const mapStateToProps = state => {
// Here you wait your data to be fetched,
// and return `isFetching` flag, in order to show a <Loader /> component,
// or something else
if (isFetching(state.posts) || isFetching(state.comments)) return { isFetching: true }
// Here the data is already fetched, and you can call your selectors.
return {
comments: state.comments,
posts: state.posts
}
}
这就是我在项目中使用的流程。正如我已经说过的那样,您可以以一种非常基本的方式开始实现它,以后(如果适合)您可以创建一些抽象,这些抽象将减少样板代码。例如-您可以创建一个HOC,仅在其中传递所需的Entities,并且在提取Entities后,HOC将呈现您的组件。诸如此类:DataProviderHOC(PostsList, ['Post', 'Comment'])
。仅在提取PostsList
个实体的情况下,Post, Comment
组件才会呈现。尽可能简单干净。