我认为您误解了“顶级”是什么。它仅仅意味着,在一个函数组件中,useSelector() 不能放在循环、条件和嵌套函数中。它与根组件或组件结构无关
// bad
const MyComponent = () => {
if (condition) {
// can't do this
const data = useSelector(mySelector);
console.log(data);
}
return null;
}
---
// good
const MyComponent = () => {
const data = useSelector(mySelector);
if (condition) {
console.log(data); // using data in condition
}
return null;
}
如果有的话,mapStateToPtops 的位置甚至比钩子调用还要高
钩子的规则使得使用特定的钩子变得非常困难。您仍然需要以某种方式从回调中的状态访问变化的值
公平地说,您几乎不必在回调中访问不断变化的值。我不记得上次我需要那个。通常,如果您的回调需要最新状态,您最好只调度一个动作,然后该动作的处理程序(redux-thunk、redux-saga、redux-observable 等)将自己访问最新状态
这只是一般钩子的细节(不仅仅是 useSelector),如果你真的想要,有很多方法可以绕过它,例如
const MyComponent = () => {
const data = useSelector(mySelector);
const latestData = useRef()
latestData.current = data
return (
<button
onClick={() => {
setTimeout(() => {
console.log(latestData.current) // always refers to latest data
}, 5000)
}}
/>
)
}
与 mapStateToProps 相比,使用 hook 除了节省代码行之外还有什么好处?
- 您无需在需要访问 store 时编写连接函数,而是在不再需要访问 store 时将其删除,从而节省时间。 react devtools 中没有无尽的包装器
- 来自 connect 的 props、来自 parent 的 props 和由来自 3rd 方库的包装器注入的 props 之间有明显的区别并且没有冲突
- 有时您(或与您一起工作的开发人员)会为
mapStateToProps 中的道具选择不明确的名称,并且您必须一直滚动到文件中的 mapStateToProps 以找出用于此特定道具的选择器.这不是钩子的情况,其中选择器和带有返回数据的变量耦合在同一行
- 通过使用钩子,您可以获得钩子的一般优势,其中最大的优点是能够耦合在一起并在多个组件中重用相关的有状态逻辑
- 使用
mapStateToProps,您通常必须处理mapDispatchToProps,这更加麻烦且更容易迷失,尤其是阅读别人的代码(对象形式?函数形式?bindActionCreators?)。来自mapDispatchToProps 的道具可以与它的动作创建者具有相同的名称,但签名不同,因为它在mapDispatchToprops 中被覆盖。如果您在多个组件中使用一个动作创建者,然后重命名该动作创建者,这些组件将继续使用来自道具的旧名称。如果你有一个依赖循环,对象形式很容易中断,而且你必须处理隐藏变量名
.
import { getUsers } from 'actions/user'
class MyComponent extends Component {
render() {
// shadowed variable getUsers, now you either rename it
// or call it like this.props.getUsers
// or change import to asterisk, and neither option is good
const { getUsers } = this.props
// ...
}
}
const mapDispatchToProps = {
getUsers,
}
export default connect(null, mapDispatchToProps)(MyComponent)