在登录和注销时启动单独的redux-saga

时间:2018-08-12 16:46:21

标签: reactjs redux react-redux redux-saga chatkit

我正在学习Redux-Saga,在将人们登录并注销时断开他们与聊天服务(Pusher的聊天工具)的正确连接时遇到了一些麻烦。

到目前为止,我有一个“ auth”传奇,它等待LOGIN_REQUEST操作,使用axios登录到REST api,然后通过调用USER_SET操作将用户名和令牌存储在存储中。

我的问题是,当登录发生并存储了凭据时,我应该放置一个名为CHAT_CONNECT之类的新动作来启动另一个传奇来连接到Chatkit,还是应该让这个传奇来收听LOGIN_SUCCESS?被解雇并对此采取行动?这两种方法在实践上甚至没有任何区别。

作为一个奖励问题,使用Redux Sagas从Chatkit接收新websocket消息并对其采取行动的最佳方法是什么?这是用于连接和接收来自chatkit的事件的样板代码。

chatManager
  .connect()
    .then(currentUser => {
      currentUser.subscribeToRoom({
        roomId: currentUser.rooms[0].id,
        hooks: {
          onNewMessage: message => {
            console.log(`Received new message: ${message.text}`)
          }
        }
      });
    })
    .catch(error => {
      console.error("error:", error);
    })

1 个答案:

答案 0 :(得分:1)

关于第一个问题:

  

我的问题是,当登录发生并存储了凭据时,我应该输入一个名为CHAT_CONNECT之类的新动作来启动另一个传奇来连接到Chatkit,还是应该让这个传奇来收听LOGIN_SUCCESS?被解雇并对此采取行动?

使用所提供的信息很难决定哪种方法是理想的,因为任何一种都可以完成相同的功能。我看到的两种提议的方法之间最大的区别是依赖性的方向。您有两个不同的“模块”(功能,程序包,...无论您调用处理单一职责的代码块如何),都可以将它们称为log-inconnect-chat

如果您从CHAT_CONNECT故事中调度动作log-in,则您的log-in模块将依赖于connect-chat模块。大概,connect-chat操作将存在于connect-chat模块中。

或者,如果您的connect-chat传奇故事等待LOGIN_SUCCESS,那么您的connect-chat模块将取决于您的log-in模块。大概LOGIN_SUCCESS将位于log-in模块中。

这两种方法都没有错。哪个最好取决于您的应用程序需求和功能。

如果您想在其他任何时间连接聊天,那么在成功登录后,可以从CHAT_CONNECT传奇中分发log-in。因为聊天不再取决于登录。在几种情况下,一种方法会比另一种更好地工作,但实际上取决于应用程序其余部分的设置方式。

关于奖励问题:

在redux-saga中挂钩外部事件的一种方法是通过eventChannel s完成的。文件:https://redux-saga.js.org/docs/api/#eventchannelsubscribe-buffer-matcher

有一些样板,但是我发现这种方法使测试更加容易,并且真正封装了外部功能。这是一个简单的示例,说明如何将事件通道连接到您提供的代码片段:

export const createOnMessageChannel = () =>
  eventChannel((emit) => {
    chatManager
      .connect()
        .then(currentUser => {
          currentUser.subscribeToRoom({
            roomId: currentUser.rooms[0].id,
            hooks: {
              onNewMessage: message => emit({ message }),
            }
          });
        })
        .catch(error => emit({ error }));

    return () => {
        // Code to unsubscribe, e.g. chatManager.disconnet() ? 
    };
  });

export function* onMessage({ message, error }) {
  if (error) {
    yield put(handleError(error));
    return;
  }

  yield put(handleMessage(message));
}

// this is what you pass to your root saga
export function* createOnMessageSaga() {

  // using call because this makes it easier to test
  const channel = yield call(createOnMessageChannel);
  if (!channel) return;

  yield takeEvery(channel, onMessage);
}