使用Redux管理视频播放器

时间:2016-03-09 18:06:31

标签: javascript reactjs redux

使用Redux管理视频播放器的理想方法是什么,主要是在调度播放/暂停视频的操作方面?

我正在React应用程序中构建视频播放器,我在视频播放器上安装了事件监听器来调度相关事件来更新状态。将父组件作用于调度PLAY或PAUSE操作的其他组件的最佳方法是什么?

例如,我想要考虑的一个用例是正在播放的一个视频以及确保暂停播放的所有其他视频。

我想到的两种方式是:

1)让父组件检查componentWillReceiveProps中的更改,并检查

之类的内容
if (this.props.paused && !nextProps.paused) {
    this.refs.video.play()
}

2)在状态树中存储对底层视频元素的引用,并使用中间件对某些操作(例如PLAY操作)执行操作,例如

if (action.type === PLAY) {
    let state = getState();
    state.players[action.payload.playerId].play();
}

一种策略会更多"正确"比另一种,还是有另一种更有意义的方式?

2 个答案:

答案 0 :(得分:2)

1)是要走的路。

您的视频只是一个视图组件。在React中,你总是希望组件的道具来决定输出。

2)的问题是视频对象不属于该状态。您过多地告诉Redux实现细节。 Redux并不关心实现细节;它只是一个国家容器。

更新

进一步思考,我建议componentDidUpdate()是放置此逻辑的最佳位置。即。

componentDidUpdate(prevProps)
  if (prevProps.paused && !this.props.paused) {
    this.refs.video.play();
  }
}

优点是在重新渲染后调用componentDidUpdate()。它可能对您的目的没有影响,但是在React有机会更新DOM之前触发DOM事件可能会导致一些不幸的竞争条件。

当然,这并没有改变我的建议的要点,即输出应始终是道具(或状态)驱动。

答案 1 :(得分:1)

我认为你不需要(2),(1)是相当不错的。现在你只处理播放动作,但你可以在那里添加暂停,如下所示:

if (this.props.paused && !nextProps.paused) {
  this.refs.video.play()
}

if (!this.props.paused && nextProps.paused) {
  this.refs.video.pause()
}

在这种情况下,您的html播放器状态将与redux播放器状态同步。

  

例如,我想要考虑的一个用例是正在播放的一个视频以及确保暂停播放的所有其他视频。

在这种情况下,您可以在减速机中处理这种情况。我会通过暂停状态的ID存储所有玩家,例如:

{
 1: {
   paused: true, 
 },
 2: {
   paused: false,
 },
 ...
}

当您收到PLAY动作时,您需要在动作中添加玩家ID并暂停其他玩家:

function players(state = {}, action) {
  switch (action.type) {
    case PAUSE: 
      return {
        ...state,
        [action.id]: {
          paused: true
        }
      }
    case PLAY: 
      const nowPlaying = Object.keys(state).find(id => !state[id].paused);
      const newState = {
        ...state,
        [action.id]: {
          paused: false
        }
      };
      if (nowPlaying) {
        newState[nowPlaying].paused = true;
      }
      return newState;
  }
}