订阅Redux中存储的单个属性更改
在Redux中,订阅(store.subscribe)是一种常见的方式,用于在存储状态更改时更新UI或执行其他操作。然而,有时我们希望只订阅特定属性的更改,而不是整个存储状态的更改。这可能是因为我们只关心特定属性的更改,或者我们希望将订阅行为细分为更小的部分。
在上面的代码示例中,有三个reducer函数:counter、messanger和latestAction。每个reducer都处理不同的属性,并在接收到相应的action时更新该属性。然后,我们使用combineReducers将这些reducer组合成一个reducer,并将其传递给createStore函数来创建store。
在创建store后,我们使用store.subscribe函数两次来订阅store的更改。第一个订阅函数检查store的action属性,如果其中包含'messanger',则打印出相应的消息。第二个订阅函数检查store的action属性,如果其中包含'counter',则打印出相应的消息。
这种做法的出现是因为我们希望根据store数据区分订阅者,并且具有多个存储的能力。通过订阅特定属性的更改,我们可以更精确地控制订阅行为,并只在特定属性更改时执行相应的操作。
解决方法是使用store.subscribe函数来订阅特定属性的更改。在订阅函数中,我们可以通过检查store的属性来确定是否应该执行相应的操作。这可以通过使用store.getState函数来获取当前的store状态,并检查相应的属性来实现。
在上面的代码示例中,我们使用store.getState().action来获取当前的action属性,并检查其中是否包含特定关键字。如果包含特定关键字,我们执行相应的操作。
这样,我们就可以根据store数据的特定属性来订阅更改,并执行相应的操作。这种做法可以帮助我们更精确地控制订阅行为,并根据需要执行不同的操作。
总结起来,通过订阅特定属性的更改,我们可以根据store数据的不同部分来区分订阅者,并执行相应的操作。这种做法可以帮助我们更精确地控制订阅行为,并根据需要执行不同的操作。
Redux只提供了一种通用的方式来知道store何时更新:subscribe方法。subscribe的回调函数没有任何关于有什么变化的信息,因为subscribe的API是有意设定为低级别的,只是简单地运行每个回调函数而没有参数。你只知道store以某种方式进行了更新。
因此,有人必须编写特定的逻辑来比较旧状态和新状态,看看是否有任何变化。你可以通过使用React-Redux来处理这个问题,为你的组件指定一个mapStateToProps函数,在你的组件中实现componentWillReceiveProps,并检查存储中的特定props是否已更改。
还有一些附加的库试图处理这种情况:https://github.com/ashaffer/redux-subscribe和https://github.com/jprichardson/redux-watch。两者都可以使用不同的方法指定要查看的状态的特定部分。
回答很可靠。只想补充一点,redux-watch和redux-subscribe都在Redux文档的Store推荐中列出了:https://redux.js.org/introduction/ecosystem#store。
问题的原因是在Redux中直接使用subscribe时,没有办法订阅store的一部分。但是,Redux的创建者自己说过,不要直接使用subscribe!为了使Redux应用程序的数据流正常工作,您需要一个包装整个应用程序的组件。该组件将订阅store。其余的组件将作为这个包装器组件的子组件,并且只会获取它们需要的状态的部分。
如果您正在使用React和Redux,那么有个好消息-官方的react-redux包会为您解决这个问题!它提供了一个名为
使用Provider组件包装根组件以订阅store更改
ReactDOM.render(
,
document.getElementById('root')
)
现在,任何被connect()包装的
const mapStateToProps = (state) => {
return {
somethingFromStore: state.somethingFromStore
}
}
class ChildOfApp extends Component {
render() {
return
}
}
//将App包装在connect中并传入mapStateToProps
export default connect(mapStateToProps)(ChildOfApp)
显然,
一个问题是,我想有一个组件来响应一个action。假设有一个组件NavBar,它触发一个action toggleDrawer。这个action将一个值存储在store中,表示drawer的状态isDrawerOpen。那么,当触发该action时,我如何使drawer打开?这里还存在一个潜在的冲突:drawer本身可以打开,并且它控制它的open属性,因此从drawer更改isDrawerOpen会导致无限循环...
在connect中仍然有代码来响应所有更改,并在比较前后的mapStateToProps返回之前至少执行一些代码,从而不必要地影响性能。我只是想知道是否可以检测所需的键的名称,例如:function mapStateToProps(({someKey, anotherReducerKey}) => ...,并且只订阅这些键。在JavaScript中,您可以获取参数的名称-因此问题是您是否可以获取这些参数的解构键的名称。
更新:以下是如何获取参数名称的方法:获取参数名称的方法:stackoverflow.com/questions/1007981/… ...然后我只是使用func.toString()来查看是否可以获取解构对象参数,确实可以!因此,我们可以重写该函数来获取您想要订阅的状态键。然后我们只需要实现一个store.subscribeByKey()函数。
然而,还有两个问题:1)我们如何以跨浏览器兼容的方式实现这一点,因为并非所有浏览器都原生支持像Chrome控制台那样的解构,2)如果这的确比connect运行mapStateToProps(以及mapDispatchToProps和mergeProps)函数更快,这将在一定程度上取决于您的应用程序,而不仅仅是connect函数。也就是说,我认为我们只需要在启动时运行它一次以获取您要监视的键,因为我认为可以静态分析connect函数调用,即在运行时不能更改。
在这个特定的例子中,export default connect...
的目的是什么?为什么要导出它?
我的意思是,如果您的应用程序是扁平的,而不是拆分成需要输入和导出的文件,那么如何将store连接到每个组件,以便它们可以访问它?