react-simple-loadable 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/loadable.d.ts +9 -2
- package/loadable.d.ts.map +1 -1
- package/loadable.js +113 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# React Simple Loadable HOC
|
|
2
2
|
|
|
3
|
-
This is simple
|
|
3
|
+
This is simple loadable component based on Class React Component
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
@@ -12,4 +12,15 @@ loadable(async () => {
|
|
|
12
12
|
},
|
|
13
13
|
SkeletonComponent
|
|
14
14
|
)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { loadable } from "react-simple-loadable";
|
|
19
|
+
|
|
20
|
+
loadable(async () => {
|
|
21
|
+
return (await import('./your-component')).YourNamedComponent
|
|
22
|
+
},{
|
|
23
|
+
loader: SkeletonComponent,
|
|
24
|
+
extra: () => <div>renders with the lazy component</div>
|
|
25
|
+
})
|
|
15
26
|
```
|
package/loadable.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { ComponentType } from 'react';
|
|
2
|
-
import { Maybe } from 'yammies/utils/types';
|
|
3
2
|
export type LoadableComponentFunction<P = Record<string, any>> = () => Promise<ComponentType<P>>;
|
|
4
|
-
|
|
3
|
+
interface LoadableConfig {
|
|
4
|
+
loader?: ComponentType<any>;
|
|
5
|
+
/**
|
|
6
|
+
* Component which renders with the lazy component
|
|
7
|
+
*/
|
|
8
|
+
extra?: ComponentType<any>;
|
|
9
|
+
}
|
|
10
|
+
export declare function loadable<P = any>(loadFn: LoadableComponentFunction<P>, loaderOrConfig?: null | undefined | LoadableConfig['loader'] | LoadableConfig): ComponentType<P>;
|
|
11
|
+
export {};
|
|
5
12
|
//# sourceMappingURL=loadable.d.ts.map
|
package/loadable.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadable.d.ts","sourceRoot":"","sources":["../src/loadable.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loadable.d.ts","sourceRoot":"","sources":["../src/loadable.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAa,aAAa,EAAE,MAAM,OAAO,CAAC;AAGjD,MAAM,MAAM,yBAAyB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,MAAM,OAAO,CAC5E,aAAa,CAAC,CAAC,CAAC,CACjB,CAAC;AAIF,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B;;OAEG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;CAC5B;AAyID,wBAAgB,QAAQ,CAAC,CAAC,GAAG,GAAG,EAC9B,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,EACpC,cAAc,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,cAAc,GAC5E,aAAa,CAAC,CAAC,CAAC,CAsBlB"}
|
package/loadable.js
CHANGED
|
@@ -1,13 +1,115 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/* eslint-disable sonarjs/sonar-no-unused-class-component-methods */
|
|
3
|
+
/* eslint-disable sonarjs/no-unsafe */
|
|
4
|
+
/* eslint-disable sonarjs/public-static-readonly */
|
|
5
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
6
|
+
import { Component } from 'react';
|
|
7
|
+
const DefaultLoader = () => null;
|
|
8
|
+
const loadingStates = new WeakMap();
|
|
9
|
+
const getOrCreateLoadingState = (loadFn) => {
|
|
10
|
+
if (!loadingStates.has(loadFn)) {
|
|
11
|
+
loadingStates.set(loadFn, {
|
|
12
|
+
error: null,
|
|
13
|
+
loading: true,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return loadingStates.get(loadFn);
|
|
17
|
+
};
|
|
18
|
+
const updateLoadingState = (loadFn, update) => {
|
|
19
|
+
const loadingState = getOrCreateLoadingState(loadFn);
|
|
20
|
+
const updatedState = { ...loadingState, ...update };
|
|
21
|
+
loadingStates.set(loadFn, updatedState);
|
|
22
|
+
return updatedState;
|
|
23
|
+
};
|
|
24
|
+
const load = (loadFn) => {
|
|
25
|
+
const state = getOrCreateLoadingState(loadFn);
|
|
26
|
+
if (state.result) {
|
|
27
|
+
return state;
|
|
28
|
+
}
|
|
29
|
+
updateLoadingState(loadFn, { loading: true, error: null });
|
|
30
|
+
state.loading = true;
|
|
31
|
+
state.error = null;
|
|
32
|
+
state.promise = loadFn()
|
|
33
|
+
.then((result) => {
|
|
34
|
+
state.loading = false;
|
|
35
|
+
state.result = result;
|
|
36
|
+
updateLoadingState(loadFn, state);
|
|
37
|
+
return result;
|
|
38
|
+
})
|
|
39
|
+
.catch((error) => {
|
|
40
|
+
state.loading = false;
|
|
41
|
+
state.error = error;
|
|
42
|
+
updateLoadingState(loadFn, state);
|
|
43
|
+
throw error;
|
|
44
|
+
});
|
|
45
|
+
updateLoadingState(loadFn, state);
|
|
46
|
+
return state;
|
|
47
|
+
};
|
|
48
|
+
class LoadableComponentBase extends Component {
|
|
49
|
+
config;
|
|
50
|
+
constructor(config, initialState, props) {
|
|
51
|
+
super(props);
|
|
52
|
+
this.config = config;
|
|
53
|
+
this.state = initialState;
|
|
54
|
+
}
|
|
55
|
+
static loadFn = undefined;
|
|
56
|
+
static preload() {
|
|
57
|
+
load(this.loadFn);
|
|
58
|
+
}
|
|
59
|
+
UNSAFE_componentWillMount() {
|
|
60
|
+
this.loadModule();
|
|
61
|
+
}
|
|
62
|
+
loadModule() {
|
|
63
|
+
if (!this.state.loading) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const { promise } = load(this.config.loadFn);
|
|
67
|
+
this.syncLoadingState();
|
|
68
|
+
promise
|
|
69
|
+
.then(() => {
|
|
70
|
+
this.syncLoadingState();
|
|
71
|
+
return null;
|
|
72
|
+
})
|
|
73
|
+
.catch(() => {
|
|
74
|
+
this.syncLoadingState();
|
|
75
|
+
return null;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
syncLoadingState() {
|
|
79
|
+
this.setState(getOrCreateLoadingState(this.config.loadFn));
|
|
80
|
+
}
|
|
81
|
+
updateLoadingState(update) {
|
|
82
|
+
this.setState(updateLoadingState(this.config.loadFn, update));
|
|
83
|
+
}
|
|
84
|
+
render() {
|
|
85
|
+
const { loader } = this.config;
|
|
86
|
+
const Loader = loader || DefaultLoader;
|
|
87
|
+
if (this.state.loading || this.state.error) {
|
|
88
|
+
return _jsx(Loader, {});
|
|
89
|
+
}
|
|
90
|
+
else if (this.state.result) {
|
|
91
|
+
const Component = this.state.result;
|
|
92
|
+
const Extra = this.config.extra;
|
|
93
|
+
return (_jsxs(_Fragment, { children: [_jsx(Component, { ...this.props }), Extra && _jsx(Extra, {})] }));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
4
100
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
5
|
-
export function loadable(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
101
|
+
export function loadable(loadFn, loaderOrConfig) {
|
|
102
|
+
const config = typeof loaderOrConfig === 'object'
|
|
103
|
+
? loaderOrConfig
|
|
104
|
+
: { loader: loaderOrConfig };
|
|
105
|
+
class LoadableComponent extends LoadableComponentBase {
|
|
106
|
+
loadFn = loadFn;
|
|
107
|
+
constructor(props) {
|
|
108
|
+
super({
|
|
109
|
+
loadFn,
|
|
110
|
+
...config,
|
|
111
|
+
}, getOrCreateLoadingState(loadFn), props);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return LoadableComponent;
|
|
13
115
|
}
|