我应该在Redux存储中存储函数引用吗?

我应该在Redux存储中存储函数引用吗?,redux,Redux,我正试图以一种惯用的React/Redux方式将键盘快捷键支持构建到我的React/Redux应用程序中。我计划这样做的方式是让以下操作创建者和关联操作: registerShortcut(keyCode, actionCreatorFuncReference) 然后,reducer将使用keyCodes到actionCreatorFuncReferences的映射更新redux存储中的registeredShortcuts对象。然后,我的根组件将侦听keyup并查看是否注册了关联的keyCo

我正试图以一种惯用的React/Redux方式将键盘快捷键支持构建到我的React/Redux应用程序中。我计划这样做的方式是让以下操作创建者和关联操作:

registerShortcut(keyCode, actionCreatorFuncReference)
然后,reducer将使用keyCodes到actionCreatorFuncReferences的映射更新redux存储中的registeredShortcuts对象。然后,我的根组件将侦听keyup并查看是否注册了关联的keyCode,如果是,则通过action creator函数引用分派映射的操作

但是,这将是我第一次在Redux存储中存储函数引用。到目前为止,我只拥有具有普通值(字符串、整数等)的键的对象

Redux文档说:“您应该尽最大努力保持状态可序列化。不要在其中放入任何您无法轻松转换为JSON的内容。”这是否表明在我的Redux存储中存储此类函数引用是一个坏主意?如果是,有什么更好的方法来完成我在React/Redux中尝试的操作


另一种方法是只将键码和函数引用的映射存储在根react组件本身中,但这感觉不太像Redux,因为现在应用程序状态不在Redux存储中。

不,您不应该将函数引用存储在Redux存储中。它们是不可序列化的,正如您所提到的,状态应该始终是可序列化的。我能想到的最有利于redux的方法就是将热键映射到他们的ActionCreatorFuncName。

我是redux新手,但在我看来,你可以传递键代码和动作类型。 然后,减速器可以侦听该动作类型并相应地进行更改

以下是使用库捕鼠器的示例:

//在您的容器上
功能寄存器端口剪切(元素、分派、键码、动作类型){
捕鼠器(元素).bind(键码,函数(e){
派遣({
类型:actionType,
有效载荷:{
keyCode:keyCode,
活动:e
}
});
});
});
mapDispatchToProps=功能(调度){
返回{
onMount:函数(元素){
registerShortcut(元素,分派,['command+f','ctrl+f'],'OPEN_SEARCH');
},
onUnmount:函数(元素){
捕鼠器(元素).unbind(['command+f','ctrl+f']);
}
};
};
//在您的组件上
componentDidMount(){
onMount(ReactDOM.findDOMNode(this));
};
组件将卸载(){
onUnmount(ReactDOM.findDOMNode(this));
};
//在你的减速机上
功能减速机(旧状态、动作){
如果(action.type==“打开搜索”){
//…做出改变//
返回新闻状态;
}
返回旧状态;
};

这样,键盘快捷键将发送一个动作。减速器将对状态进行必要的更改。最后,应用程序可以重新渲染。

TL;医生:你不知道。存储状态必须始终可序列化(正如Nathan回答的那样)。 Redux方式为via,或Redux可观察方式为via

NL;PR:根据Redux文档,您希望在操作中传递引用(1),忽略它(2)并在增强中使用它(3):

/。。。在你的行动中:
const data={val:1},ref=()=>{};
const action={type:'action_WITH_REF',data,REF}//(1)
//... 在减速器中:
案例“带参考号的行动”:
返回{…状态,数据:action.data}//(2)
//... 在你的增强器中:
从“redux”导入{createStore,applyMiddleware};
从“./reducers”导入减速机;
导出常量myRefStore={};
 
函数refHandler({getState}){
返回下一步=>action=>{
开关(action.type){
//这可以通过一个可观察的redux更优雅地完成
案例“带参考号的行动”:
myRefStore.aRef=action.ref;//(3)
打破
}
//一定要维护连锁店
const returnValue=下一步(操作);
//否则,你的午餐会破坏商店
返回值;
};
} 
const store=createStore(
减速器,
初始状态,
applyMiddleware(参考处理程序)
);
注意:只要你的增强剂没有副作用,你就可以服用了。请注意,您可以直接在减速器中获得参考,但这种方法将参考保持在减速器级别,并且忽略了
combineReducers()
的要点。使用增强器,您可以将它们放在一个位置(
myRefStore


最后一个观察结果是redux存储不是任何数据存储,而是状态存储,因此我们需要在增强器中处理函数和其他非状态相关的内容。您可以利用增强子主干,通过注入
myRefStore

这是一个有趣的想法。然后我将如何从actionCreatorFuncNames字符串实际执行函数?我认为这将取决于应用程序的详细信息。无论您在哪里处理这些关键事件,都可以轻松地将所有操作导入到单个
actions
对象中。困难的部分是将按下按钮的上下文化,并使用适当的参数调用
操作[actionCreatorFuncNameA]
。另一方面,如果热键都是切换键,那么就不需要调用任何参数,问题就解决了。这有意义吗,还是我错了?在您的存储中存储函数是可以的——只要您知道所涉及的权衡。在常见问题解答中:“如果您对持久性和时间旅行调试等可能无法正常工作的事情没有意见,那么完全欢迎您将不可序列化的项目放入您的Redux存储。”谁说Redux存储应该是可序列化的?除非你做服务器渲染,否则我看不到避免它的价值。看起来Redux已经改变了对这个问题的看法