Reputation: 2936
I'm building an app that contains a store with an "offers" section of the state tree (ImmutableJS List Object). I need to take some action (play a browser sound) whenever an item is added to this list. Items can be added to this list via several different types of Redux actions.
I am trying to figure out the best way to react to the changes to a particular part of the store. I could do it in each action/reducer method, but then I would have it all over the place. I'd rather have one central place to handle the logic.
What's the best way to handle this? Should I create a generic store subscriber and has it's own logic for keeping track of the list values?
Upvotes: 3
Views: 1963
Reputation: 843
In this case your best bet is a store listener. Either a plain listener function or a redux connected React component.
Assuming a simple function to make noise:
function playSound () {
const audio = new Audio('audio_file.mp3')
audio.play()
}
You can create a store observer and listen for changes:
function createSoundObserver (store) {
let prevState = store.getState()
return store.subscribe(() => {
const nextState = store.getState()
if (prevState.messages.length < nextState.messages.length) {
playSound()
}
prevState = nextState
})
}
You can achieve the same with a React component:
import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
class Notifier extends Component {
static propTypes = {
messages: PropTypes.array.isRequired
}
componentDidUpdate (prevProps) {
if (this.props.messages.length > prevProps.messages.length) {
playSound()
}
}
render () { return null }
}
export default connect((state, props) => {
const {messages} = state
return {messages}
}, {})(Notifier)
As long as a Notifier is present amongst the rendered tree, it will check for changes and play the sound accordingly. The advantage of this approach is that you don't have to take extra care of unsubscribing the event if you want to stay quiet, and it seamlessly works server-side rendering.
Upvotes: 8