Merge branch 'fix-typo-drive' into 'main'
[ProtonMail-WebClient.git] / packages / unleash / useFlagsReady.ts
blobf38d2b5bca5853ef748aa737c0399e52768c3ebd
1 import { useEffect } from 'react';
3 import { useUnleashClient } from '@unleash/proxy-client-react';
5 import { createPromise } from '@proton/shared/lib/helpers/promise';
7 type SimpleFunc = () => void;
9 const readyCallbackSet: Set<SimpleFunc> = new Set();
10 const errorCallbackSet: Set<SimpleFunc> = new Set();
12 // Memoize initial states to keep value consistency between hook instances
13 let readyInitialState = false;
14 let readyPromise = createPromise<void>();
16 /**
17  * useFlagsReady
18  *
19  * @description
20  * This hooks is a custom override of `useFlagsStatus` function from unleash React SDK.
21  * Unleash React client `useFlagsStatus` hook:   https://github.com/Unleash/proxy-client-react/blob/main/src/useFlagsStatus.ts
22  * Unleash React client context Provider:        https://github.com/Unleash/proxy-client-react/blob/main/src/FlagProvider.tsx
23  *
24  * It returns `flagsReady` and `flagsError` based on the `ready` and `error` Unleash JS client event emitter.
25  * JS client: https://github.com/Unleash/unleash-proxy-client-js/blob/main/src/index.ts#L61
26  *
27  * Error event has an issue in the react client so in the meantime this stands as our own hotfix
28  * https://github.com/Unleash/proxy-client-react/pull/127
29  *
30  * @returns {boolean}
31  */
32 const useFlagsReady = () => {
33     const client = useUnleashClient();
35     useEffect(() => {
36         const readyListener = () => {
37             readyCallbackSet.forEach((callback) => callback());
38         };
39         const readyCallback: SimpleFunc = () => {
40             if (readyInitialState === false) {
41                 readyPromise.resolve();
42                 readyInitialState = true;
43             }
44         };
45         const errorListener = () => {
46             errorCallbackSet.forEach((callback) => callback());
47         };
49         if (readyCallbackSet.size === 0) {
50             client.on('ready', readyListener);
51             client.on('error', errorListener);
52         }
54         readyCallbackSet.add(readyCallback);
55         errorCallbackSet.add(readyCallback);
57         return () => {
58             readyCallbackSet.delete(readyCallback);
59             errorCallbackSet.delete(readyCallback);
60             if (readyCallbackSet.size === 0) {
61                 client.off('ready', readyListener);
62                 client.off('error', errorListener);
63             }
64         };
65     }, []);
67     return readyPromise.promise;
70 export default useFlagsReady;