如何在@stomp/stomp-js 库的onStompErrorCallback 中使用dispatch? [英] How to use dispatch inside onStompErrorCallback of @stomp/stomp-js library?
问题描述
我的目标是不重复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:
当用户登录时,例如在名为
LoginScreen
的组件中,有一个名为login
的方法.login
的方法做了两件事:
When a user login, e.g in a component called
LoginScreen
there is a method calledlogin
. Thelogin
's method do 2 things:
- 向 API 发送 POST 请求并获取令牌作为响应.
- 进行
WebSocket握手
,然后StompCommand.CONNECT
,StompCommand.SUBSCRIBE
.
如果用户按下登录按钮
,它将调用该方法.
If the user press the login button
, it will invoke the method.
当用户打开应用时:
App
组件将发送一个 GET 请求来验证令牌.如果令牌没有过期,它会做WebSocket握手
,然后StompCommand.CONNECT
,和StompCommand.SUBSCRIBE
.
- The
App
component will send a GET request to authenticate the token. If the token is not expired, it will do theWebSocket handshake
, and thenStompCommand.CONNECT
, andStompCommand.SUBSCRIBE
.
问题是:
- 每个场景都需要访问
onStompErrorCallback
,我不能把它放在任何地方而不复制代码增加代码味道
,因为它取决于dispatch(doSomething())
.
- Each scenario needs access to the
onStompErrorCallback
, and I can't put it anywhere without duplicating the codeincrease code smell
since it dependsdispatch(doSomething())
.
我尝试过的:
我尝试将
new Client(stompConfig: StompConfig)
存储到 redux.
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:
- 应用
- 身份验证层
- WebSocketLayer
他打!登录并打开应用场景,它会按预期工作.
Ta Da! Either login and open the app scenario, it would work as expected.
推荐答案
解决方案?创建第二层身份验证:
The solution? Create a 2nd Layer authentication:
- 应用:这是
Redux
和NavigationContainer
所在的位置. - AuthenticationLayer:这是
Stack.Navigator
所在的位置,例如
- App: This is where the
Redux
andNavigationContainer
lives. - AuthenticationLayer: This is where the
Stack.Navigator
lives, e.g
return (
<Stack.Navigator>
authenticated ? <Stack.Screen component={LoginScreen} /> : <Stack.Screen component={HomeScreen} />
</Stack.Navigator>
)
- 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屋!