关于javascript:Reducer中的调度调度

Schedule dispatch in reducer

我知道当您要异步分派动作时,存在类似redux thunk的解决方案。但是,最近我有以下情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import {store} from"./store";

const initialState = {
  todos: []
}
a€?
function todoApp(state = initialState, action) {    
a€?  
  if(action.type =="ACTION_A"){
    // 1. do smth with state
    // 2. do smth with state, and then... schedule a dispatch say using setTimeout:
    setTimeout(()=>store.dispatch({type:"ACTION_B", payload:1}), 2000);  
    return state;
  }// check other actions e.g. ACTION_B etc.

  return state;    
}

您可以看到ACTION_B不是我想从其他地方发出的动作,比如说是一个异步动作(这样我就可以使用redux thunk了),而是ACTION_A中逻辑的一部分。

我的问题是:在redux中如何处理这种情况?

PS。这个答案说,安排在reducer中调度是很好的(我在上面的情况),甚至可以使用中间件提供一些解决方案。但是,我在博客文章中遵循了该解决方案(请参见该答案的评论),并在博客上看到Mark Erikson(Redux的维护者)的评论,但这仍然不是正确的方法。他似乎建议针对这种情况使用redux-loop。

我的问题是在redux中处理此类情况的正确方法是什么?
除了redux-loop之外,还有其他解决方案吗?

还是我们仍然可以使用redux thunk解决这种情况?


这是一个很好的例子:

1
2
3
4
5
6
7
8
const actionA = () = ({ dispatch, getState }) => {
   dispatch(actionA1) // dispatch another action that will change the state

   setTimeout(()=> {
       const { data } = getState();
       dispatch({type:"ACTION_B", payload: data });
   }, 2000);
}

或自定义中间件,它将安排超时,但将允许actionA继续运行到reducer并更改状态(这将在超时之前发生,因为它是同步的):

1
2
3
4
5
6
7
8
9
10
const middleware = ({ dispatch, getState }) = next => action => {
   if(action.type =="ACTION_A"){ //
       setTimeout(()=> {
           const { data } = getState();
           dispatch({type:"ACTION_B", payload: data });
       }, 2000);
   }

   next(action);
}

通常,reducer应该是纯函数,即没有诸如调度或调度动作之类的副作用。如果某个动作除了改变状态还需要执行其他操作,则应使用中间件(例如thunk)来执行。