我为仪表板提供了以下简化组件。仪表板对象通过道具注入。 handleDeleteDashboard操作检查仪表板是否不是最后一个可用的仪表板。如果是,则不允许删除它。对于这个检查,我需要从mapStateToProps中的商店获得的nrOfDashboards。所以我将Component连接到redux商店。
class Dashboard extends Component {
constructor(props) {
super(props);
this.handleDeleteDashboard = this.handleDeleteDashboard.bind(this);
}
handleDeleteDashboard() {
const { dashboardDeleteAction, dashboard, nrOfDashboards } = this.props;
if (nrOfDashboards < 2) {
// NOT Allowed to delete
} else {
dashboardDeleteAction(dashboard.id);
}
}
render() {
const { dashboard } = this.props;
return (
<Content>
<h1>{dashboard.name}</h1>
<Button onButtonClick={this.handleDeleteDashboard}>Delete</Button>
</Content>
);
}
}
Dashboard.propTypes = {
dashboard: customPropTypes.dashboard.isRequired,
nrOfDashboards: PropTypes.number.isRequired
};
function mapStateToProps(state) {
return {
nrOfDashboards: selectNrOfDashboards(state)
}
}
export default connect(mapStateToProps, { dashboardDeleteAction: dashboardActionCreators.dashboardDelete })(Dashboard);
但现在,只要nrOfDashboards发生变化,Component就会订阅商店并进行更新(我知道我可以在这里执行一个shouldComponentUpdate来防止重新渲染,但这不是重点)。所以我基本上订阅了nrOfDashboards的更改,虽然我在主动点击删除按钮时只需要这些信息。
所以我想出了一个替代解决方案,我将Component从商店中断开,并通过handleDeleteDashboard方法中的上下文访问商店。
class Dashboard extends Component {
constructor(props) {
...
}
handleDeleteDashboard() {
const { dashboardDeleteAction, dashboard } = this.props;
const store = this.context;
if (selectNrOfDashboards(store.getState()) < 2) {
// NOT Allowed to delete
} else {
dashboardDeleteAction(dashboard.id);
}
}
render() {
...
}
}
Dashboard.propTypes = {
dashboard: customPropTypes.dashboard.isRequired,
};
Dashboard.contextTypes = {
store: PropTypes.object
};
export default connect(null, { dashboardDeleteAction: dashboardActionCreators.dashboardDelete })(Dashboard);
这对我来说很好,每当我主动点击按钮时,我都会确保从商店获得新鲜状态。无论如何,我之前没有在其他地方看过这种技术,也读过一些访问商店的地方不应该在mapStateToProps之外完成。但我的问题是,如果按需直接访问商店是一种反模式,如果我最好应该遵循代码示例一,我将组件连接到商店?
答案 0 :(得分:1)
是。直接访问商店被认为是反模式。惯用Redux代码使用基本依赖注入 - connect()
及其mapState()
和mapDispatch()
参数为您提供组件所需的数据和对dispatch
的引用,以及Redux-Thunk等中间件通过动作创建者,您可以访问getState()
和dispatch()
。
理想情况下,您的组件只会调度一个动作创建者,让动作创建者逻辑担心是否真正发送一个真实动作。因此,在您的情况下,这可能看起来像:
// action creator
export function deleteDashboard(dashboardID) {
return (dispatch, getState) => {
const state = getState();
const numberOfDashboards = selectNumberOfDashboards(state);
if(numberOfDashboards >= 2) {
dispatch({
type : "DELETE_DASHBOARD",
payload : {
dashboardID
}
});
}
}
}
// component
handleDeleteDashboard() {
const {dashboard} = this.props;
this.props.dispatch(deleteDashboard(dashboard.id));
}
请参阅有关此主题的Redux常见问题解答:http://redux.js.org/docs/FAQ.html#store-setup-multiple-stores