如何在@stomp/stomp-js 库的onStompErrorCallback 中使用dispatch?

IT技术 reactjs react-native react-redux react-navigation
2021-04-29 12:23:37

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

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

翻译:博士

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

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

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

但是这会带来问题,因为有两种情况:

  1. 当用户登录时,例如在一个被调用的组件中,LoginScreen有一个被调用的方法loginlogin的方法做两件事情:

    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: () => void,或者new Client(stompConfig: StompConfig). 它会抛出一个错误。

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

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

  3. 我尝试使用 thunk onStompErrorCallback

    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. 网络套接字层

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

1个回答

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

  1. 应用程序:这是ReduxNavigationContainer生活的地方。
  2. AuthenticationLayer:这是Stack.Navigator生活的地方,例如
return (
  <Stack.Navigator>
    authenticated ? <Stack.Screen component={LoginScreen} /> : <Stack.Screen component={HomeScreen} />
  </Stack.Navigator>
)
  1. 网络套接字层
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.

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