Redux Saga 阻塞

Redux Saga Blocking

我是 Redux Saga 和一般生成器的新手,所以我正在努力思考如何在分派后执行其余代码之前 "await" 分派的动作。

例如:

    // 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 传递给调度并在 saga 中触发 setIsLoading 来绕过它,但这不是最优雅的解决方案,如果有的话,我想知道更好的过程。

有什么想法或建议吗?非常感谢。

由于您的操作只是简单的同步函数,因此无法跟踪组件内的 isLoading 状态。您必须将 isLoading 保留在 redux 存储中,并连接到您的组件。每当调度 GET_THREAD_MESSAGES_SUCCESS 操作时,reducer 会将 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;
  }
}