如何在@stomp/stomp-js 库的 onStompErrorCallback 内部使用 dispatch? TL:DR编辑

问题描述

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

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

TL:DR

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

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

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

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

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

    1. 向 API 发送 POST 请求并获取令牌作为响应。
    2. 先做WebSocket handshake,然后是StompCommand.CONNECTStompCommand.SUBSCRIBE

    如果用户按下 login button,它将调用方法

  2. 用户打开应用时:

    1. App 组件将发送一个 GET 请求来验证令牌。如果令牌没有过期,它会执行 WebSocket handshake,然后是 StompCommand.CONNECT,然后是 StompCommand.SUBSCRIBE

问题是:

  1. 每个场景都需要访问 onStompErrorCallback,我不能在不复制代码 increase code smell 的情况下将它放在任何地方,因为它取决于 dispatch(doSomething())

我尝试过的:

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

    Redux 无法存储 onStopErrorCallback: () => voidnew Client(stompConfig: StompConfig)。它会抛出错误

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

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

  3. 我尝试对 onStompErrorCallback

    使用 thunk

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

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

编辑

这是我可以用自定义钩子做的最好的事情。这不是一个解决方案,useStompClient 将 stompClient 视为 null,尽管它不是,然后重新渲染(这次它看到 stompClient 为非 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;

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

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

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

解决方法

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

  1. 应用:这是 ReduxNavigationContainer 所在的位置。
  2. AuthenticationLayer:这是 Stack.Navigator 所在的位置,例如
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.

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...