Skip to content

Instantly share code, notes, and snippets.

@riskers
Last active October 14, 2020 07:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save riskers/7af616dbaf610a452f04a5822809c3e5 to your computer and use it in GitHub Desktop.
Save riskers/7af616dbaf610a452f04a5822809c3e5 to your computer and use it in GitHub Desktop.
reselect / immutablejs

在 reducer 中,都是返回一个新对象,否则组件是不会更新 ui 的。而返回新对象,可以:

  • Object.assign:比较 hack,每次新生成一个对象
  • ...state
  • immutable.js

主要用来缓存衍生数据的:就是从 store 中的 A、B 要衍生出 C,就可以使用 reselect 来优化性能,避免重复计算。

demo

假设这样的 conatiner 结构:

<div>
   <Count />
   <Posts />
</div>

Count 每 500ms 执行一次自加,不光 Count 的 reducer 会过一遍 mapStateToProps,Posts 的 reducer 也会过一遍。这是必然的,因为 connect 就是这样设计的


这样本没有什么问题,但是,一旦 Posts 的 mapStateToProps 是需要产生衍生数据的,即使 Posts 的 reducer 没有变化,也还是要随着 Count 每 1000ms 计算,浪费性能:

// 每次 Count 的 reducer ,Post 的 reducer 就也要变化,这本来无所谓
// 但是每 500ms 需要计算一次,是很浪费性能的。
const mapStateToProps = state => {
  const postsById = state.postsById
  const usersById = state.usersById
  const postListing = state.postListing

  return {
    posts: postListing.map(id => {
      const post = postsById[id];
      return {...post, user: usersById[post.author]}
    })
  }
}

使用 reselect 优化:

// 这样子,就可以做到:只有 postsById、usersById、postListing 其中之一变化时才会重新计算 posts
const getListing = createSelector(
  state => state.postsById,
  state => state.usersById,
  state => state.postListing,
  (posts, users, listing) => listing.map(id => {
    const post = posts[id];
    return {...post, user: users[post.author]}
  })
);

const mapStateToProps = (state) => {
  return {posts: getListing(state)};
};

reselect 使用场景:

  • 缓存计算结果,节省性能
@riskers
Copy link
Author

riskers commented Sep 18, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment