Redux:我如何让两个减速器以特定顺序响应相同的动作?

问题描述:

我是比较新的终极版,和我有以下情况:Redux:我如何让两个减速器以特定顺序响应相同的动作?

  1. 我的应用程序,使一个AJAX请求的响应回来,并调度{type: 'RECEIVE_FIRST_MESSAGE', message}从服务器获取的第一个“消息”对象
  2. MessageReducer通过处理RECEIVE_FIRST_MESSAGE

    A)加入到action.messagestate.messages

    B)进行另一AJAX调用来获取下一条消息(如果action.message.hasNextMessage

  3. SessionReducer也处理RECEIVE_FIRST_MESSAGE,加入action.message.sessionIdstate.session.id

这里只有一个问题:当我取第二消息,我需要使用我从第一条消息获得的sessionId。但是因为MessageReducerSessionReducer之前运行,所以会话ID不在MessageReducer尝试发出第二个AJAX请求时的状态。

我可以通过使用超时来“解决”这个问题,以确保MessageReducer在1ms之后不会使其成为第二个请求,但是这感觉像是一种黑客/反模式。

TLDR

当我有:

  • 其对于state(由两个不同的减速处理)两个部分组成
  • 我想触发一个AJAX调用数据的动作反应,从减速机A
  • 我想添加一些状态(state.session.id)作为回应,从减速机B

如何确保减速器B在减速器A使AJAX调用(以不会使丹阿布拉莫夫哭泣的方式)之前添加状态?

+1

您是否使用过像redux thunk或sagas这样的东西?如果它已经在您正在处理的消息中,为什么它需要从会话中获取它?但是:你在减速器中进行Ajax调用? –

+0

是的,我正在使用thunk。至于为什么我会从'状态'中得到身份证......我想现在我想到了,我不知道。我只是在想“一个动作会将ID添加到状态中,一个单独的动作会将ID从状态中拉出来”,但是由于(如您所述),我已经拥有了我在动作中需要的所有内容,并通过'state'是完全不必要的(好吧,除了以后的请求,但那些没有时间问题)。谢谢!如果你想把一些东西说成“按照定义在这种情况下你已经拥有了你需要的一切”的话,我会很高兴地接受它。 – machineghost

第一件事是第一件事。切勿在减速器内进行AJAX调用。永远。 https://www.youtube.com/watch?v=Q-lv8kyYrqQ

Reducer函数应该是纯粹的,没有任何副作用(如HTTP请求)。相反,使用thunks是有利的。下面是你如何做到这一点的例子。

从服务器获取第一条消息响应后,您会发送RECEIVE_FIRST_MESSAGE操作。这将同步更新状态原子。完成后,您可以检查消息是否有下一条消息。如果确实如此,则派遣新的异步操作以获取下一条消息。在该异步操作创建器内部,您可以从状态原子获取会话标识,该标识保证会根据之前分派的RECEIVE_FIRST_MESSAGE操作进行更新。

让我知道如果您有任何问题。

// getFirstMessageFromServer() and getNextMessageFromServer() are thunks and async action creators 
// fetchFirstMessage() and fetchNextMessage() make HTTP requests 

function getFirstMessageFromServer() { 
    return (dispatch, getState) => { 
    return fetchFirstMessage() 
     .then(message => { 
     dispatch({ type: 'RECEIVE_FIRST_MESSAGE', message }); 
     if (message.hasNextMessage) dispatch(getNextMessageFromServer()); 
     return message; 
     }); 
    }; 
} 

function getNextMessageFromServer() { 
    return (dispatch, getState) => { 
    const { id: sessionId } = getState().session.id; 
    return fetchNextMessage(sessionId) 
     .then(nextMessage => { 
     dispatch({ type: 'RECEIVE_NEXT_MESSAGE', message: nextMessage }); 
     return nextMessage; 
     }); 
    }; 
} 


const rootReducer = combineReducers({ 
    session: sessionReducer, 
    messages: messagesReducer 
}); 

const initialMessages = []; 

function messagesReducer(state = initialMessages, action) { 
    switch(action.type) { 
    case 'RECEIVE_FIRST_MESSAGE': 
     return state.concat(action.message); 
    case 'RECEIVE_NEXT_MESSAGE': 
     return state.concat(action.message); 
    default: 
     return state; 
    } 
} 

const initialSession = { id: null }; 

function sessionReducer(state = initialSession, action) { 
    switch(action.type) { 
    case 'RECEIVE_FIRST_MESSAGE': 
     return { 
     ...state, 
     id: action.message.sessionId 
     }; 
    default: 
     return state; 
    } 
} 
+0

这是有道理的:当我有一分钟我会尝试重构委托调出的减速机,并按照你的模式。谢谢。 – machineghost