Redux 与 React - 与组件共享商店的正确方式
Redux with React - right way to share the store with components
来自 Redux 的商店服务最终被 React App 中的各种组件使用。它公开的方法(如dispatch、getState和subscribe)被各种组件(如容器或展示)使用。
我认为传递此商店服务的方法是一个重要的设计决策。我看到两种方法,它们是:
1) 通过将商店作为道具传递给所有嵌套级别的每个组件。这不是推荐的。
2) 使用像 react-redux 这样的工具,它在上下文的帮助下,使商店(准确地说是状态和调度)在需要的地方可用。
我的问题是:为什么不直接在需要的地方导入商店。对于基于 SPA 的 React App,store 将是一个单例。嵌套在任何级别的组件都可以简单地导入商店。为什么我们要采用以上两种方法中的任何一种?
对于任何嵌套级别的组件:我们可以这样做吗
import store from "path/to/store";
let MyComponent = () => {
let state = store.getState();
return (
<div onClick={() => {
store.dispatch({
type: "SOME_EVENT",
payload: store.somedata
});
}}>{state.dataINeedHere}</div>
);
};
export default MyComponent;
而不是
import { connect } from "react-redux";
let MyComponent = ({somedata, onMyAction}) => {
let state = store.getState();
return (
<div onClick={() => {
onMyAction(somedata);
}}>{somedata}</div>
);
};
const mapStateToProps = (state) => {
return {
somedata: state.somedata
}
}
const mapDispatchToProps = (dispatch) => {
return {
onMyAction: (input) => {
dispatch({
type: "SOME_EVENT",
payload: input
});
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
考虑当您有第二个 MyComponent 时会发生什么,它管理来自商店不同部分的数据。你的选择是告诉每个人如何 access/update 它的数据:
<Container>
<MyComponent path="/a/b/c" />
<MyComponent path="/a/b/d" />
</Container>
或者您可以只授予每个访问权限:
<Container>
<!-- context /a/b was passed to Container -->
<MyComponent data={c} onUpdate={update(c)} />
<MyComponent data={d} onUpdate={update(d)} />
</Container>
后者使 MyComponent 更加简单和灵活。
Redux 常见问题解答涵盖了这个问题,位于 http://redux.js.org/docs/FAQ.html#store-setup-multiple-stores。
总结:当您可以 直接导入商店时,您将代码绑定到该商店的实现,这使得它的可重用性降低并且更难测试。理想情况下,none 您自己的代码实际上曾经直接引用商店。连接组件、中间件和 thunked 动作创建者都通过依赖注入接收相关的 dispatch
和 getState
函数引用,使它们可重用并允许轻松模拟行为以进行测试。
来自 Redux 的商店服务最终被 React App 中的各种组件使用。它公开的方法(如dispatch、getState和subscribe)被各种组件(如容器或展示)使用。
我认为传递此商店服务的方法是一个重要的设计决策。我看到两种方法,它们是:
1) 通过将商店作为道具传递给所有嵌套级别的每个组件。这不是推荐的。
2) 使用像 react-redux 这样的工具,它在上下文的帮助下,使商店(准确地说是状态和调度)在需要的地方可用。
我的问题是:为什么不直接在需要的地方导入商店。对于基于 SPA 的 React App,store 将是一个单例。嵌套在任何级别的组件都可以简单地导入商店。为什么我们要采用以上两种方法中的任何一种?
对于任何嵌套级别的组件:我们可以这样做吗
import store from "path/to/store";
let MyComponent = () => {
let state = store.getState();
return (
<div onClick={() => {
store.dispatch({
type: "SOME_EVENT",
payload: store.somedata
});
}}>{state.dataINeedHere}</div>
);
};
export default MyComponent;
而不是
import { connect } from "react-redux";
let MyComponent = ({somedata, onMyAction}) => {
let state = store.getState();
return (
<div onClick={() => {
onMyAction(somedata);
}}>{somedata}</div>
);
};
const mapStateToProps = (state) => {
return {
somedata: state.somedata
}
}
const mapDispatchToProps = (dispatch) => {
return {
onMyAction: (input) => {
dispatch({
type: "SOME_EVENT",
payload: input
});
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
考虑当您有第二个 MyComponent 时会发生什么,它管理来自商店不同部分的数据。你的选择是告诉每个人如何 access/update 它的数据:
<Container>
<MyComponent path="/a/b/c" />
<MyComponent path="/a/b/d" />
</Container>
或者您可以只授予每个访问权限:
<Container>
<!-- context /a/b was passed to Container -->
<MyComponent data={c} onUpdate={update(c)} />
<MyComponent data={d} onUpdate={update(d)} />
</Container>
后者使 MyComponent 更加简单和灵活。
Redux 常见问题解答涵盖了这个问题,位于 http://redux.js.org/docs/FAQ.html#store-setup-multiple-stores。
总结:当您可以 直接导入商店时,您将代码绑定到该商店的实现,这使得它的可重用性降低并且更难测试。理想情况下,none 您自己的代码实际上曾经直接引用商店。连接组件、中间件和 thunked 动作创建者都通过依赖注入接收相关的 dispatch
和 getState
函数引用,使它们可重用并允许轻松模拟行为以进行测试。