kla*_*anm 171 reducers reactjs redux
是否可以在减速机本身发送动作?我有一个进度条和一个音频元素.目标是在音频元素中更新时间时更新进度条.但是我不知道将ontimeupdate事件处理程序放在何处,或者如何在ontimeupdate的回调中调度一个动作来更新进度条.这是我的代码:
//reducer
const initialState = {
audioElement: new AudioElement('test.mp3'),
progress: 0.0
}
initialState.audioElement.audio.ontimeupdate = () => {
console.log('progress', initialState.audioElement.currentTime/initialState.audioElement.duration);
//how to dispatch 'SET_PROGRESS_VALUE' now?
};
const audio = (state=initialState, action) => {
switch(action.type){
case 'SET_PROGRESS_VALUE':
return Object.assign({}, state, {progress: action.progress});
default: return state;
}
}
export default audio;
Run Code Online (Sandbox Code Playgroud)
ebu*_*989 133
在reducer中调度动作是一种反模式.您的reducer应该没有副作用,只需消化动作有效负载并返回一个新的状态对象.在reducer中添加侦听器和调度操作可能会导致链接操作和其他副作用.
听起来像是初始化的AudioElement类,事件监听器属于组件而不是状态.在事件监听器中,您可以调度一个将progress在状态下更新的操作.
您可以AudioElement在新的React组件中初始化类对象,也可以只将该类转换为React组件.
class MyAudioPlayer extends React.Component {
constructor(props) {
super(props);
this.player = new AudioElement('test.mp3');
this.player.audio.ontimeupdate = this.updateProgress;
}
updateProgress () {
// Dispatch action to reducer with updated progress.
// You might want to actually send the current time and do the
// calculation from within the reducer.
this.props.updateProgressAction();
}
render () {
// Render the audio player controls, progress bar, whatever else
return <p>Progress: {this.props.progress}</p>;
}
}
class MyContainer extends React.Component {
render() {
return <MyAudioPlayer updateProgress={this.props.updateProgress} />
}
}
function mapStateToProps (state) { return {}; }
return connect(mapStateToProps, {
updateProgressAction
})(MyContainer);
Run Code Online (Sandbox Code Playgroud)
请注意,它updateProgressAction会自动包装,dispatch因此您无需直接调用dispatch.
Mar*_*oni 129
在减速器完成之前开始另一次调度是一种反模式,因为当您的减速器完成时,您在减速器开始时收到的状态将不再是当前的应用状态.但是在reducer中安排另一个调度并不是反模式.事实上,这就是Elm语言所做的,正如您所知道的,Redux是尝试将Elm架构引入JavaScript.
这是一个中间件,它将属性添加asyncDispatch到您的所有操作中.当您的reducer完成并返回新的应用程序状态时,asyncDispatch将触发store.dispatch您给它的任何操作.
// This middleware will just add the property "async dispatch"
// to actions with the "async" propperty set to true
const asyncDispatchMiddleware = store => next => action => {
let syncActivityFinished = false;
let actionQueue = [];
function flushQueue() {
actionQueue.forEach(a => store.dispatch(a)); // flush queue
actionQueue = [];
}
function asyncDispatch(asyncAction) {
actionQueue = actionQueue.concat([asyncAction]);
if (syncActivityFinished) {
flushQueue();
}
}
const actionWithAsyncDispatch =
Object.assign({}, action, { asyncDispatch });
const res = next(actionWithAsyncDispatch);
syncActivityFinished = true;
flushQueue();
return res;
};
Run Code Online (Sandbox Code Playgroud)
现在你的减速机可以做到这一点:
function reducer(state, action) {
switch (action.type) {
case "fetch-start":
fetch('wwww.example.com')
.then(r => r.json())
.then(r => action.asyncDispatch({ type: "fetch-response", value: r }))
return state;
case "fetch-response":
return Object.assign({}, state, { whatever: action.value });;
}
}
Run Code Online (Sandbox Code Playgroud)
cha*_*vdw 11
您可以尝试使用像redux-saga这样的库.它允许以非常简洁的方式对异步函数进行排序,触发操作,使用延迟等.它非常强大!
| 归档时间: |
|
| 查看次数: |
93159 次 |
| 最近记录: |