Skip to content

Commit 0c77946

Browse files
committed
add safety nets
1 parent fe0e971 commit 0c77946

File tree

5 files changed

+49
-18
lines changed

5 files changed

+49
-18
lines changed

src/babel.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import {resolve, relative, dirname} from 'path';
22
// @ts-ignore
33
import * as crc32 from "crc-32";
44

5-
export const encipherImport = (str: string) => crc32.str(str).toString(32);
5+
export const encipherImport = (str: string) => {
6+
return crc32.str(str).toString(32);
7+
};
68

79
// Babel v7 compat
810
let syntax: any;

src/loadable.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function toLoadable<T>(firstImportFunction: Promised<T>, autoImport = true): Loa
6363
},
6464

6565
replaceImportFunction(newImportFunction) {
66-
importFunction=newImportFunction;
66+
importFunction = newImportFunction;
6767
},
6868

6969
then(cb, err) {
@@ -102,8 +102,12 @@ function toLoadable<T>(firstImportFunction: Promised<T>, autoImport = true): Loa
102102
},
103103

104104
reload() {
105-
this.promise = undefined;
106-
return this.load();
105+
if(this.promise) {
106+
this.promise = undefined;
107+
108+
return this.load();
109+
}
110+
return Promise.resolve();
107111
},
108112

109113
load() {
@@ -171,7 +175,12 @@ export const dryRender = (renderFunction: () => void) => {
171175
};
172176

173177
export const assignImportedComponents = (set: Array<Promised<any>>) => {
174-
set.forEach(imported => toLoadable(imported))
178+
const countBefore = LOADABLE_SIGNATURE.size;
179+
set.forEach(imported => toLoadable(imported));
180+
if (countBefore === LOADABLE_SIGNATURE.size) {
181+
console.error('react-imported-component: no import-marks found, please check babel plugin')
182+
}
183+
done();
175184
};
176185

177186
export function executeLoadable(importFunction: DefaultImport<any> | Loadable<any>) {

src/marks.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,22 @@ export const rehydrateMarks = (marks?: string[]) => {
5858
const rehydratedMarks: string[] = marks || (global as any).___REACT_DEFERRED_COMPONENT_MARKS || [];
5959
const tasks: Promise<any>[] = [];
6060

61+
const usedMarks = new Set<string>();
62+
6163
LOADABLE_MARKS
6264
.forEach(({mark, loadable}) => {
6365
if (allIn(mark, rehydratedMarks)) {
66+
mark.forEach(m => usedMarks.add(m));
6467
tasks.push(loadable.load())
6568
}
6669
});
6770

71+
rehydratedMarks.forEach(m => {
72+
if (!usedMarks.has(m)) {
73+
throw new Error(`react-imported-component: unknown mark(${m}) has been used. Client and Server should have the same babel configuration.`);
74+
}
75+
});
76+
6877
return Promise.all(tasks);
6978
};
7079

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export interface Loadable<T> {
5050
tryResolveSync<Y = T>(then: (x: T) => Y): Promise<Y>;
5151

5252
load(): Promise<T>;
53-
reload(): Promise<T>;
53+
reload(): Promise<void>;
5454

5555
then(callback: (x: T) => void, err: () => void): Promise<any>;
5656
}

src/useImported.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,34 @@ interface ImportedShape<T> {
2424
retry(): void;
2525
}
2626

27-
export function useLoadable<T>(loadable: Loadable<T>) {
28-
if(isBackend && !isItReady()) {
29-
console.error('react-imported-component: trying to render not ready component. Have you `await whenComponentsReady()`?')
30-
}
27+
interface HookOptions {
28+
import?: boolean;
29+
track?: boolean;
30+
}
3131

32+
export function useLoadable<T>(loadable: Loadable<T>, options: HookOptions = {}) {
3233
const UID = useContext(streamContext);
3334
const [, forceUpdate] = useState(() => {
3435
// use mark
35-
useMark(UID, loadable.mark);
36-
loadable.loadIfNeeded();
36+
if (options.import !== false) {
37+
if (options.track !== false) {
38+
useMark(UID, loadable.mark);
39+
}
40+
loadable.loadIfNeeded();
41+
}
3742

3843
return {};
3944
});
4045

4146
useEffect(() => {
42-
loadLoadable(loadable, forceUpdate);
43-
}, [loadable]);
47+
if (options.import !== false) {
48+
loadLoadable(loadable, forceUpdate);
49+
}
50+
}, [loadable, options.import]);
51+
52+
if (isBackend && !isItReady() && loadable.isLoading()) {
53+
console.error('react-imported-component: trying to render not ready component. Have you `await whenComponentsReady()`?')
54+
}
4455

4556
// use mark
4657
// retry
@@ -54,8 +65,8 @@ export function useLoadable<T>(loadable: Loadable<T>) {
5465
}, [loadable]);
5566

5667
if (process.env.NODE_ENV !== 'production') {
57-
if(isBackend) {
58-
if(!loadable.done) {
68+
if (isBackend) {
69+
if (!loadable.done) {
5970
console.error('react-imported-component: using not resolved loadable. You should `await whenComponentsReady()`.')
6071
}
6172
}
@@ -68,14 +79,14 @@ export function useLoadable<T>(loadable: Loadable<T>) {
6879
};
6980
}
7081

71-
export function useImported<T, K = T>(importer: DefaultImport<T> | Loadable<T>, exportPicker: (x: T) => K = es6import): ImportedShape<K> {
82+
export function useImported<T, K = T>(importer: DefaultImport<T> | Loadable<T>, exportPicker: (x: T) => K = es6import, options: HookOptions = {}): ImportedShape<K> {
7283
const [topLoadable] = useState(getLoadable(importer));
7384
const postEffectRef = useRef(false);
7485
const {
7586
loadable,
7687
retry,
7788
update,
78-
} = useLoadable<T>(topLoadable);
89+
} = useLoadable<T>(topLoadable, options);
7990

8091
// kick loading effect
8192
useEffect(() => {

0 commit comments

Comments
 (0)