Yon*_*Nir 32 javascript reactjs react-redux react-hooks
在创建 React 应用程序时,如果我使用 hook useSelector,我需要遵守 hooks 调用规则(只能从功能组件的顶层调用它)。如果我使用mapStateToProps,我会在道具中获得状态,我可以在任何地方使用它而没有任何问题......同样的问题useDispatch
与使用钩子相比,除了节省代码行之外,使用钩子还有什么好处mapStateToProps?
dec*_*ele 20
Redux 存储状态可以从组件中的任何位置读取和更改,包括回调。每当存储状态发生更改时,组件都会重新呈现。当组件重新渲染时, useSelector 再次运行,并为您提供更新的数据,以后可以在您想要的任何地方使用。这是一个示例以及useDispatch回调内部的用法(在根级别分配之后):
function Modal({ children }) {
const isOpen = useSelector(state => state.isOpen);
const dispatch = useDispatch();
function handleModalToggeled() {
// using updated data from store state in a callback
if(isOpen) {
// writing to state, leading to a rerender
dispatch({type: "CLOSE_MODAL"});
return;
}
// writing to state, leading to a rerender
dispatch({type: "OPEN_MODAL"});
}
// using updated data from store state in render
return (isOpen ? (
<div>
{children}
<button onClick={handleModalToggeled}>close modal</button>
</div>
) : (
<button onClick={handleModalToggeled}>open modal</button>
);
);
}
Run Code Online (Sandbox Code Playgroud)
使用 mapStateToProps/mapDispatchToProps 没有什么是使用 useSelector 和 useDispatch 钩子做不到的。
话虽如此,这两种方法之间存在一些值得考虑的差异:
TL;DR - 最终结论:每种方法都有其优点。Connect 更成熟,出现奇怪错误和边缘情况的可能性较小,并且具有更好的关注点分离。Hooks 更易于阅读和编写,因为它们位于使用它们的地方附近(全部在一个独立的组件中)。此外,它们更易于与 TypeScript 一起使用。最后,它们可以很容易地升级到未来的 React 版本。
我认为您误解了“顶级”是什么。它仅仅意味着,在函数组件内部,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;
}
Run Code Online (Sandbox Code Playgroud)
如果有的话,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)
}}
/>
)
}
Run Code Online (Sandbox Code Playgroud)
与 mapStateToProps 相比,除了节省代码行之外,使用钩子还有什么好处?
mapStateToProps,您必须一直滚动到mapStateToProps文件中以找出用于此特定 props 的选择器。这不是钩子的情况,其中选择器和变量及其返回的数据耦合在同一行mapStateToProps你通常要处理mapDispatchToProps哪个更麻烦更容易迷路,尤其是阅读别人的代码(对象形式?函数形式?bindActionCreators?)。来自的 PropmapDispatchToProps可以与它的动作创建者具有相同的名称,但具有不同的签名,因为它在mapDispatchToprops. 如果您在多个组件中使用一个动作创建器,然后重命名该动作创建器,这些组件将继续使用来自 props 的旧名称。如果您有依赖循环,并且您必须处理阴影变量名称,则对象形式很容易中断.
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)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13833 次 |
| 最近记录: |