我是Redux Saga和生成器的新手,所以正试图了解如何在执行调度后的其余代码之前 "等待 "一个调度动作。
比如说
// Sideeffect to load messages on mount
useEffect(() => {
let mounted = true;
if(mounted) {
dispatch({ type: 'GET_THREAD_MESSAGES', threadId: _id })
setIsLoading(false);
}
return () => {
dispatch({ type: 'CLEAR_FOCUSSED_MESSAGES' })
}
}, [])
当组件第一次挂载时,它将会派发 GET_THREAD_MESSAGES
. 我注意到了上述行动在我 rootSaga
有以下内容。
export default function* rootSaga() {
yield all([
...
watchGetThreadMessages(),
watchClearFocussedMessages()
])
}
我的适用传奇。
export function* watchGetThreadMessages() {
yield takeEvery('GET_THREAD_MESSAGES', getThreadMessages)
}
export function* getThreadMessages({ threadId, lastDate }) {
const { token } = yield select(state => state.auth);
try {
const { data } = yield call(getMessages, token, threadId)
yield put({
type: 'GET_THREAD_MESSAGES_SUCCESS',
allMessages: data.messages,
totalMessages: data.count
})
console.log('retrieved messages')
} catch(err) {
console.log(err)
}
}
getMessages
是一个axios调用我的端点从服务器获取数据。 问题是,我的 setIsLoading
元器件安装后 dispatch
将会在我完成从axios调用中获取消息之前启动,因为它是异步的。 通常情况下,如果我在组件内部获取数据,我就会等待这个响应,但是我不知道如何等待这个 dispatch
动作。 我已经通过将我的setIsLoading传递给dispatch,然后在saga内部启动setIsLoading来解决这个问题,但这不是最优雅的解决方案,如果有更好的过程,我想知道。
有什么想法或建议吗? 任何都非常感谢。
因为你的动作只是普通的同步函数,所以没有办法追踪到你的动作。isLoading
状态在一个组件内。你必须保持 isLoading
并连接到你的组件。每当 GET_THREAD_MESSAGES_SUCCESS
动作发出后,减速器将改变 isLoading
值为 false
. 例如,你的信息还原器可能看起来像下面这样
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
// isLoading prop is mapped to state.messages.isLoading
function YourComponent({ isLoading, dispatch }) {
useEffect(() => {
dispatch({ type: 'GET_THREAD_MESSAGES', threadId: 'someId' });
}, []);
if(isLoading) {
return <div>Some loader</div>;
}
return <div>Your component</div>;
}
function mapStateToProps(state) {
return {
isLoading: state.messages.isLoading,
};
}
export default connect(mapStateToProps)(YourComponent);
你的信息还原器可能看起来像下面这样。
export default function messagesReducer(state, action) {
switch (action.type) {
case 'GET_THREAD_MESSAGES':
return {
...state,
isLoading: true,
};
case 'GET_THREAD_MESSAGES_SUCCESS':
return {
...state,
isLoading: false,
allMessages: action.allMessages,
totalMessages: action.totalMessages,
};
default:
return state;
}
}