通过id重新选择createSelector

And*_*eff 6 reactjs redux react-redux reselect react-hooks

我在我的 React 项目中使用 reselect lib。

我已经创建了Posts工作正常的选择器。这是代码

// selectors.ts

const getPosts = (state: RootState) => state.posts.posts;

export const getPostsSelector = createSelector(getPosts, (posts) => posts);
Run Code Online (Sandbox Code Playgroud)

我在我的页面上这样称呼它

// SomePage.tsx    
const posts = useSelector(getPostsSelector);
Run Code Online (Sandbox Code Playgroud)

现在我需要通过 id 获取帖子。我想这样做:

// selectors.ts

const getPostDetail = (state: RootState) =>
  state.posts.posts.entities[ID];

export const getPostsById = createSelector(
  getPostDetail,
  (detail) => detail
);
Run Code Online (Sandbox Code Playgroud)

并在页面上调用:

const PostDetail = useSelector(getPostsById);
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

  • 获得单一职位的正确方法是吗?
  • 如果是,如何传递帖子 ID 如果不是,如何正确处理?

Dre*_*ese 1

按具体情况来选择并不是正确的做法id。该useSelector钩子不允许将更多内容传递state给选择器。

一个迂回的解决方案可能是将specific帖子id也存储到状态中并选择它。缺点是该帖子在初始渲染时不可用,您需要分派(从useEffect挂钩或回调)一个操作来存储您想要的帖子id

const getPostById = createSelector(
  [getPostsSelector, getPostId],
  (posts, id) => posts.find(post => post.id === id);
);
Run Code Online (Sandbox Code Playgroud)

用法:

const postById = useSelector(getPostById);

...

dispatch(setPostId(postId)); // store the id
Run Code Online (Sandbox Code Playgroud)

由于您无法创建一个选择器来id直接返回特定帖子,因此我建议创建一个选择器来返回帖子的派生状态对象,这有助于更快的查找,即地图或对象。

例子:

const postDetailMap = createSelector(
  [getPosts],
  posts => posts.reduce((posts, post) => ({
    ...posts,
    [post.id]: post,
  }), {}),
);
Run Code Online (Sandbox Code Playgroud)

用法:

const postsMap = useSelector(postDetailMap);

const specificPost = postMap[postId];
Run Code Online (Sandbox Code Playgroud)

不过,您也许可以将其抽象为自定义挂钩。

const useGetPostById = id => {
  const postsMap = useSelector(postDetailMap);
  return postsMap[id];
}
Run Code Online (Sandbox Code Playgroud)

用法:

const post = useGetPostById(postId);
Run Code Online (Sandbox Code Playgroud)