首页 > 解决方案 > Redux Saga 阻塞

问题描述

我是 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 调用,从服务器获取数据。问题是,在我完成从 axios 调用中获取消息之前,我setIsLoading的组件安装后会触发,因为它是异步的。dispatch通常,如果我在组件内获取数据,我只会等待此响应,但不确定如何等待dispatch操作。我已经通过将我的 setIsLoading 传递给调度并在 saga 中触发 setIsLoading 来解决它,但这不是最优雅的解决方案,如果有的话,我想知道一个更好的过程。

有什么想法或建议吗?任何人都非常感谢。

标签: react-nativereduxgeneratorredux-saga

解决方案


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

推荐阅读