Skip to content

Commit 525d001

Browse files
feat(): introduce useCreateChatClient hook
1 parent 24d2a4d commit 525d001

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

Diff for: src/components/Chat/hooks/useCreateChatClient.ts

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { useEffect, useState } from 'react';
2+
3+
import {
4+
DefaultGenerics,
5+
ExtendableGenerics,
6+
OwnUserResponse,
7+
StreamChat,
8+
TokenOrProvider,
9+
UserResponse,
10+
} from 'stream-chat';
11+
12+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13+
const makeCancellable = <T extends (...functionArguments: any[]) => any>(
14+
functionToCancel: T,
15+
delay: number,
16+
) => {
17+
let timeout: NodeJS.Timeout | null = null;
18+
19+
const start = (...functionArguments: Parameters<T>) =>
20+
new Promise<ReturnType<T>>((resolve, reject) => {
21+
if (timeout) return reject(new Error('"start" has been already called'));
22+
timeout = setTimeout(() => {
23+
timeout = null;
24+
try {
25+
resolve(functionToCancel(...functionArguments));
26+
} catch (error) {
27+
reject(error);
28+
}
29+
}, delay);
30+
});
31+
32+
const cancel = () => {
33+
if (timeout === null) return;
34+
clearTimeout(timeout);
35+
timeout = null;
36+
};
37+
38+
return [cancel, start] as const;
39+
};
40+
41+
/**
42+
* React hook to create, connect and return `StreamChat` client.
43+
*/
44+
export const useCreateChatClient = <SCG extends ExtendableGenerics = DefaultGenerics>({
45+
apiKey,
46+
tokenOrProvider,
47+
userData,
48+
}: {
49+
apiKey: string;
50+
tokenOrProvider: TokenOrProvider;
51+
userData: OwnUserResponse<SCG> | UserResponse<SCG>;
52+
}) => {
53+
const [chatClient, setChatClient] = useState<StreamChat<SCG> | null>(null);
54+
55+
useEffect(() => {
56+
const client = new StreamChat<SCG>(apiKey);
57+
let didUserConnectInterrupt = false;
58+
59+
const connectionPromise = client.connectUser(userData, tokenOrProvider).then(() => {
60+
if (!didUserConnectInterrupt) setChatClient(client);
61+
});
62+
63+
return () => {
64+
didUserConnectInterrupt = true;
65+
setChatClient(null);
66+
connectionPromise
67+
.then(() => client.disconnectUser())
68+
.then(() => {
69+
console.log(`Connection for user "${userData.id}" has been closed`);
70+
});
71+
};
72+
// eslint-disable-next-line react-hooks/exhaustive-deps
73+
}, [apiKey, userData.id, tokenOrProvider]);
74+
75+
return chatClient;
76+
};
77+
78+
/**
79+
* React hook to create, connect and return `StreamChat` client with debounced connector.
80+
* Delays initial connection by the specified `cancellationTimeout` (defaults to 200 ms).
81+
* Useful for applications where there's a need to switch users extremely fast without initiating connection.
82+
*/
83+
export const useCancelableCreateChatClient_UNSTABLE = <
84+
SCG extends ExtendableGenerics = DefaultGenerics
85+
>({
86+
apiKey,
87+
cancellationTimeout = 200,
88+
tokenOrProvider,
89+
userData,
90+
}: {
91+
apiKey: string;
92+
tokenOrProvider: TokenOrProvider;
93+
userData: OwnUserResponse<SCG> | UserResponse<SCG>;
94+
cancellationTimeout?: number;
95+
}) => {
96+
const [chatClient, setChatClient] = useState<StreamChat<SCG> | null>(null);
97+
98+
useEffect(() => {
99+
const client = new StreamChat<SCG>(apiKey);
100+
101+
let didUserConnectInterrupt = false;
102+
const [cancel, start] = makeCancellable(client.connectUser, cancellationTimeout);
103+
const connectionPromise = start(userData, tokenOrProvider).then(() => {
104+
// in case user missed cancelation timeout
105+
// but the connection has been initiated
106+
if (!didUserConnectInterrupt) setChatClient(client);
107+
});
108+
109+
return () => {
110+
cancel();
111+
didUserConnectInterrupt = true;
112+
setChatClient(null);
113+
connectionPromise
114+
.then(() => client.disconnectUser())
115+
.then(() => {
116+
console.log(`Connection for user "${userData.id}" has been closed`);
117+
});
118+
};
119+
// eslint-disable-next-line react-hooks/exhaustive-deps
120+
}, [apiKey, userData.id, tokenOrProvider]);
121+
122+
return chatClient;
123+
};

Diff for: src/components/Chat/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './Chat';
22
export * from './hooks/useChat';
33
export * from './hooks/useCustomStyles';
4+
export * from './hooks/useCreateChatClient';

0 commit comments

Comments
 (0)