【问题标题】:Redux Saga BlockingRedux Saga 阻塞
【发布时间】:2020-05-15 02:57:32
【问题描述】:

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

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

【问题讨论】:

    标签: react-native redux generator redux-saga


    【解决方案1】:

    由于您的操作只是普通的同步函数,因此无法跟踪组件内的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;
      }
    }
    

    【讨论】:

    • 非常感谢。我有一个可能是解决方案的感觉,但想在我发疯之前确保将所有这些状态添加到我的 redux 存储中。谢谢。