“ 在使用全局state状态时,我们其实可以用到connect下的mapStateToProps方法,也可以使用hooks钩子useSelector;在公司开发项目时,使用的是hooks钩子函数useSelector,然后出现了性能上的问题,导致页面出现了多次渲染,带着这个疑问去看useSelector源码发现了其中的蹊跷。”
首先先来思考一下connect下的mapStateToProps方法以及useSelector方法,这两种写法是否是等价的,代码如下所示:
1 | const state => { |
首先给出答案:这两种写法并不等价。我们使用方法二useSelector会导致redux的整个store的任何值变化,都会触发Test的渲染。这时候你是不是会发出很大的疑问,为什么会出现这种情况呢?让我们带着疑问继续往下探索。
其实connect它默认使用的是shallowEqual浅比较,在我最前面的文章中是仔细的介绍了这个方法的,在这篇文章中我就不讲了,感兴趣的小伙伴可以看看我这篇文章。
PureComponent和Component的区别—涉及源码
useSelector它默认使用的是refEquality引用值比较,其实在useSelector的源码中可以看到它的默认方法是refEquality方法,代码如下图所示:
我们再去看看refEquality又是个什么玩意儿,其实它很简单,就一行代码,如下图所示:
现在你是不是觉得恍然大悟了呢?refEquality方法的比较就用了一个===全等于来比较,虽说两个对象长得一模一样,但是由于它们的引用地址并不相同,那么永远用全等于都是false不相等。
通过上面的代码解析之后,我们在使用useSelector方法时,应该尽可能将其细腻化、具体化,而不能像使用connect方法一样构造一个对象返回。举一个例子,对于上面上面的代码,在使用useSelector时优化代码如下所示:
1 | // 推荐使用方法 |
如果你觉得这样写太麻烦了,那么还有一种方法可以解决,那么就是给useSelector传递第二个参数shallowEqual方法(react-redux提供的方法,等价于lodash中的isEqual方法),这样就不会使用默认的refEquality方法,代码如下所示:
1 | import { shallowEqual } from 'react-redux' |
在了解到这两个方法不同实现原理后,可以更加方便我们在以后日常开发中避免一些不必渲染,造成一些性能问题,如果你觉得这篇文章对你有帮助的话,麻烦点个赞或者关注一下公众号,以后会不定期的更新一些干货哟。