如何在@stomp/stomp-js 库的onStompErrorCallback 中使用dispatch? [英] How to use dispatch inside onStompErrorCallback of @stomp/stomp-js library?

查看:118
本文介绍了如何在@stomp/stomp-js 库的onStompErrorCallback 中使用dispatch?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是不重复onStompErrorCallback回调.

My goal is to not duplicate onStompErrorCallback callback.

ps:我正在研究另一种解决方案,我认为它会奏效.

ps: I am working on another solution, I think it would work.

目前的解决方案是在 React Hook 中直接编写 onStopErrorCallback.

The current solution is to write onStopErrorCallback directly in React Hook.

function LoginScreen() {
  const dispatch = useDispatch();

  const onStopErrorCallback = (receipt: IFrame) => {
    dispatch(doSomething());   
  }
}

然而这会带来问题,因为有两种情况:

However this poses problem, because there are 2 scenarios:

  1. 当用户登录时,例如在名为 LoginScreen 的组件中,有一个名为 login 的方法.login 的方法做了两件事:

  1. When a user login, e.g in a component called LoginScreen there is a method called login. The login's method do 2 things:

  1. 向 API 发送 POST 请求并获取令牌作为响应.
  2. 进行WebSocket握手,然后StompCommand.CONNECTStompCommand.SUBSCRIBE.

如果用户按下登录按钮,它将调用该方法.

If the user press the login button, it will invoke the method.

当用户打开应用时:

  1. App 组件将发送一个 GET 请求来验证令牌.如果令牌没有过期,它会做WebSocket握手,然后StompCommand.CONNECT,和StompCommand.SUBSCRIBE.
  1. The App component will send a GET request to authenticate the token. If the token is not expired, it will do the WebSocket handshake, and then StompCommand.CONNECT, and StompCommand.SUBSCRIBE.

问题是:

  1. 每个场景都需要访问onStompErrorCallback,我不能把它放在任何地方而不复制代码增加代码味道,因为它取决于dispatch(doSomething()).
  1. Each scenario needs access to the onStompErrorCallback, and I can't put it anywhere without duplicating the code increase code smell since it depends dispatch(doSomething()).

我尝试过的:

  1. 我尝试将 new Client(stompConfig: StompConfig) 存储到 redux.

  1. I tried to store new Client(stompConfig: StompConfig) to redux.

Redux 无法存储 onStopErrorCallback: () =>void,或 new Client(stompConfig: StompConfig).它会抛出一个错误.

Redux can't store onStopErrorCallback: () => void, or the new Client(stompConfig: StompConfig). It will throw an error.

我尝试使用自定义钩子,例如 useStompClient(X_Auth_Token: string).

I tried to use custom hook, e.g useStompClient(X_Auth_Token: string).

每次组件或屏幕调用 useStompClient(X_Auth_Token: string) 时,它都会创建新的 stompClient 而不是使用现有的 stompClient.

Each time a component or screen call useStompClient(X_Auth_Token: string), it creates new stompClient instead of using the existing stompClient.

我尝试对 onStompErrorCallback

stompClient 无法连接/订阅/发送消息.

The stompClient can't connect / subscribe / send message.

const onStompErrorCallback = (receipt: IFrame): AppThunk => dispatch => {
  dispatch(doSomething());
}

编辑

这是我可以用自定义钩子做的最好的事情.这不是一个解决方案,useStompClient 将 stompClient 视为 null,尽管它不是,然后重新渲染(这次它看到 stompClient 为非 null).

Edit

This is the best I can do with custom hook. This is not a solution, the useStompClient see stompClient as null although it's not, and then it's re-render (this time it see stompClient as not null).

let stompClient: Client | null = null;

function useStompClient(X_Auth_Token: string) {
  const dispatch = useDispatch();

  if (stompClient === null && X_Auth_Token !== '') {
    const onConnectCallback = () => {
      console.log('STOMP: connecting');
      stompClient?.subscribe('/user/queue/messages', (message) => {
        const payload = JSON.parse(message.body);
        console.log(payload);
      });
    };

    const onStompErrorCallback = (receipt: IFrame) => {
      if (receipt.headers.message.endsWith('Access is denied')) {
        stompClient?.deactivate();
        dispatch(eraseCredentials());
      }
    };

    const stompConfig: StompConfig = {
      brokerURL: `${environment.wsBaseURL}/chat`,
      forceBinaryWSFrames: true,
      appendMissingNULLonIncoming: true,
      connectHeaders: {
        'X-Auth-Token': X_Auth_Token,
      },
      onConnect: onConnectCallback,
      onStompError: onStompErrorCallback,
    };

    stompClient = new Client(stompConfig);
  }

  return stompClient;
}

export default useStompClient;

解决方案?创建第二层身份验证:

The solution? Create a 2nd Layer authentication:

  1. 应用
  2. 身份验证层
  3. WebSocketLayer

他打!登录并打开应用场景,它会按预期工作.

Ta Da! Either login and open the app scenario, it would work as expected.

推荐答案

解决方案?创建第二层身份验证:

The solution? Create a 2nd Layer authentication:

  1. 应用:这是 ReduxNavigationContainer 所在的位置.
  2. AuthenticationLayer:这是 Stack.Navigator 所在的位置,例如
  1. App: This is where the Redux and NavigationContainer lives.
  2. AuthenticationLayer: This is where the Stack.Navigator lives, e.g

return (
  <Stack.Navigator>
    authenticated ? <Stack.Screen component={LoginScreen} /> : <Stack.Screen component={HomeScreen} />
  </Stack.Navigator>
)

  1. WebSocketLayer

The WebSocketLayer requirements:
1. The `authenticated` is set to true, meaning the app already have the token and ready to be used.
2. Create the `onStompErrorCallback`, etc.
3. Put the stompClient and create a custom setters somewhere outside the React function.
4. Use React.useEffect() to set the stompClient.

他打!登录并打开应用场景,它会按预期工作.

Ta Da! Either login and open the app scenario, it would work as expected.

这篇关于如何在@stomp/stomp-js 库的onStompErrorCallback 中使用dispatch?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆