基于 Redux store 变化的动作(播放声音)

Actions (playing sound) based on Redux store changes

我正在构建一个应用程序,其中包含一个带有状态树(ImmutableJS 列表对象)的 "offers" 部分的商店。每当将项目添加到此列表时,我都需要采取一些措施(播放浏览器声音)。可以通过几种不同类型的 Redux 操作将项目添加到此列表中。

我正在尝试找出对商店特定部分的变化做出反应的最佳方式。我可以在每个 action/reducer 方法中做到这一点,但我会把它放在所有地方。我宁愿有一个中心位置来处理逻辑。

处理此问题的最佳方法是什么?我是否应该创建一个通用商店订阅者并拥有自己的逻辑来跟踪列表值?

在这种情况下,最好的选择是商店监听器。普通监听器函数或 redux 连接的 React 组件。

假设一个简单的函数来制造噪音:

function playSound () {
  const audio = new Audio('audio_file.mp3')
  audio.play()
}

您可以创建一个存储观察器并监听变化:

function createSoundObserver (store) {
  let prevState = store.getState()

  return store.subscribe(() => {
    const nextState = store.getState()

    if (prevState.messages.length < nextState.messages.length) {
      playSound()
    }

    prevState = nextState
  })
}

您可以使用 React 组件实现同样的效果:

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)

只要渲染树中存在通知程序,它就会检查变化并相应地播放声音。这种方法的优点是,如果您想保持安静,则无需特别注意取消订阅事件,并且它可以无缝地在服务器端呈现。