Skip to content

Commit adffcaa

Browse files
ukorvlUriy Korotovskikh
authored andcommitted
add lazyWithRetry utility #174
1 parent 1b54a61 commit adffcaa

File tree

5 files changed

+127
-5
lines changed

5 files changed

+127
-5
lines changed

src/features/routing/constants/routesConfig.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,27 @@ import AuthContainer from '@/features/auth/components/AuthContainer/AuthContaine
1616
import Layout from '@/features/shared/components/Layout/Layout';
1717
import { Footer, Navbar } from '@/features/shared';
1818
import { Path } from '../models/Paths';
19+
import lazyWithRetry from '../utils/lazyWithRetry';
1920

20-
const MarketView = lazy(
21+
const MarketView = lazyWithRetry(
2122
() => import(/* webpackChunkName: "MarketView" */ '../../../views/MarketView'),
23+
'MarketView',
2224
);
23-
const LoginView = lazy(
25+
const LoginView = lazyWithRetry(
2426
() => import(/* webpackChunkName: "LoginView" */ '../../../views/LoginView'),
27+
'LoginView',
2528
);
26-
const PortfolioView = lazy(
29+
const PortfolioView = lazyWithRetry(
2730
() => import(/* webpackChunkName: "PortfolioView" */ '../../../views/PortfolioView'),
31+
'PortfolioView',
2832
);
29-
const Page404 = lazy(() => import(/* webpackChunkName: "Page404" */ '../../../views/404'));
30-
const RegisterView = lazy(
33+
const Page404 = lazyWithRetry(
34+
() => import(/* webpackChunkName: "Page404" */ '../../../views/404'),
35+
'Page404',
36+
);
37+
const RegisterView = lazyWithRetry(
3138
() => import(/* webpackChunkName: "RegisterView" */ '../../../views/RegisterView'),
39+
'RegisterView',
3240
);
3341

3442
/**
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* @file Lazy load component with page reload on error.
3+
* It helps to avoid the situation when the user is stuck on the page with a broken chunk.
4+
*/
5+
6+
import { lazy } from 'react';
7+
import { SessionStorageAPI } from '@/packages/sessionStorageAdapter';
8+
9+
type ComponentImportType = () => Promise<{ default: React.ComponentType }>;
10+
11+
const sessionKey = 'lazyWithRetry';
12+
13+
/**
14+
* Lazy load component with page reload on error.
15+
*
16+
* @param componentImport - function that returns a promise with a component.
17+
* @param name - name of the component.
18+
* @returns - lazy loaded component.
19+
*/
20+
const lazyWithRetry = (componentImport: ComponentImportType, name: string) => {
21+
return lazy(async () => {
22+
const hasRefreshed = SessionStorageAPI.getItem(`${sessionKey}-${name}`) || 'false';
23+
24+
try {
25+
SessionStorageAPI.setItem(`${sessionKey}-${name}`, 'false');
26+
return await componentImport();
27+
} catch (error) {
28+
if (hasRefreshed === 'false') {
29+
SessionStorageAPI.setItem(`${sessionKey}-${name}`, 'true');
30+
window.location.reload();
31+
}
32+
33+
if (hasRefreshed === 'true') throw new Error('chunkLoadError', error);
34+
}
35+
return await componentImport();
36+
});
37+
};
38+
39+
export default lazyWithRetry;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* @file Session storage API.
3+
* @copyright Yury Korotovskikh <[email protected]>
4+
*/
5+
6+
import type { SessionStorageKey } from './SessionStorageKey';
7+
8+
/**
9+
* Session storage API.
10+
*/
11+
class SessionStorage {
12+
/**
13+
* Get sesstionStorage item.
14+
*
15+
* @param ItemKey - Key.
16+
* @returns Item value.
17+
*/
18+
public getItem<T>(ItemKey: SessionStorageKey): T | undefined {
19+
try {
20+
const serialisedValue = sessionStorage.getItem(ItemKey);
21+
if (serialisedValue === null) {
22+
return undefined;
23+
}
24+
return JSON.parse(serialisedValue);
25+
} catch {
26+
return undefined;
27+
}
28+
}
29+
30+
/**
31+
* Set sessionStorage item.
32+
*
33+
* @param ItemKey - Key.
34+
* @param ItemValue - Value.
35+
*/
36+
public setItem<T>(ItemKey: SessionStorageKey, ItemValue: T): void {
37+
try {
38+
const serialisedValue = JSON.stringify(ItemValue);
39+
sessionStorage.setItem(ItemKey, serialisedValue);
40+
} catch {
41+
// Do nothing
42+
}
43+
}
44+
45+
/**
46+
* Remove item from sessionStorage.
47+
*
48+
* @param ItemKey - Key.
49+
*/
50+
public removeItem(ItemKey: SessionStorageKey): void {
51+
try {
52+
sessionStorage.removeItem(ItemKey);
53+
} catch {
54+
// Do nothing
55+
}
56+
}
57+
}
58+
59+
export const SessionStorageAPI = new SessionStorage();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* @file Type declaration.
3+
* @copyright Yury Korotovskikh <[email protected]>
4+
*/
5+
6+
/**
7+
* Session storage avialiable keys.
8+
*/
9+
export type SessionStorageKey = `lazyWithRetry-${string}`;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* @file Index.
3+
* @copyright Yury Korotovskikh <[email protected]>
4+
*/
5+
6+
export { SessionStorageAPI } from './SessionStorage';
7+
export type { SessionStorageKey } from './SessionStorageKey';

0 commit comments

Comments
 (0)