在onClick处理程序中使用context.store.getState()是否被视为反模式



我有以下用于仪表板的简化组件。仪表板对象是通过道具注入的。handleDeleteDashboard操作检查仪表板是否不是最后一个可用的仪表板。如果是,你不允许删除它。为了这个检查,我需要从mapStateToProps中的商店获得的nrOfDashboard。因此,我将组件连接到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发生变化时就会更新(我知道我可以在这里执行shouldComponentUpdate以防止if重新渲染,但这不是重点)。所以我基本上是在订阅nrOfDashboard上的更改,尽管我只需要在主动点击删除按钮时才需要这些信息。

因此,我提出了一个替代解决方案,即断开组件与商店的连接,并通过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之外进行。但我的问题是,直接按需访问商店是否是一种反模式,如果我最好遵循代码示例一,在哪里我将组件连接到商店?

是。直接进入商店被认为是一种反模式。Idiomatic 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-设置多个存储

相关内容

最新更新