Redux:我如何让两个减速器以特定顺序响应相同的动作?
我是比较新的终极版,和我有以下情况:Redux:我如何让两个减速器以特定顺序响应相同的动作?
- 我的应用程序,使一个AJAX请求的响应回来,并调度
{type: 'RECEIVE_FIRST_MESSAGE', message}
从服务器获取的第一个“消息”对象 -
我
MessageReducer
通过处理RECEIVE_FIRST_MESSAGE
:A)加入到
action.message
state.messages
B)进行另一AJAX调用来获取下一条消息(如果
action.message.hasNextMessage
) 我
SessionReducer
也处理RECEIVE_FIRST_MESSAGE
,加入action.message.sessionId
到state.session.id
这里只有一个问题:当我取第二消息,我需要使用我从第一条消息获得的sessionId
。但是因为MessageReducer
在SessionReducer
之前运行,所以会话ID不在MessageReducer
尝试发出第二个AJAX请求时的状态。
我可以通过使用超时来“解决”这个问题,以确保MessageReducer
在1ms之后不会使其成为第二个请求,但是这感觉像是一种黑客/反模式。
TLDR
当我有:
- 其对于
state
(由两个不同的减速处理)两个部分组成 - 我想触发一个AJAX调用数据的动作反应,从减速机A
- 我想添加一些状态(
state.session.id
)作为回应,从减速机B
如何确保减速器B在减速器A使AJAX调用(以不会使丹阿布拉莫夫哭泣的方式)之前添加状态?
第一件事是第一件事。切勿在减速器内进行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;
}
}
这是有道理的:当我有一分钟我会尝试重构委托调出的减速机,并按照你的模式。谢谢。 – machineghost
您是否使用过像redux thunk或sagas这样的东西?如果它已经在您正在处理的消息中,为什么它需要从会话中获取它?但是:你在减速器中进行Ajax调用? –
是的,我正在使用thunk。至于为什么我会从'状态'中得到身份证......我想现在我想到了,我不知道。我只是在想“一个动作会将ID添加到状态中,一个单独的动作会将ID从状态中拉出来”,但是由于(如您所述),我已经拥有了我在动作中需要的所有内容,并通过'state'是完全不必要的(好吧,除了以后的请求,但那些没有时间问题)。谢谢!如果你想把一些东西说成“按照定义在这种情况下你已经拥有了你需要的一切”的话,我会很高兴地接受它。 – machineghost