-
-
Notifications
You must be signed in to change notification settings - Fork 495
Expand file tree
/
Copy pathrenderComponent.ts
More file actions
61 lines (60 loc) · 2.28 KB
/
renderComponent.ts
File metadata and controls
61 lines (60 loc) · 2.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import * as React from "react";
import type { RenderableProps } from "./types";
// shared logic between components that use either render prop,
// children render function, or component prop
export default function renderComponent<T>(
props: RenderableProps<T> & Partial<T> & Record<string, any>,
lazyProps: Record<string, any>,
name: string,
): React.ReactNode {
const { render, children, component, ...rest } = props;
if (component) {
// FIX: Don't use Object.assign which tries to overwrite getters
// Instead, create a new object with lazyProps descriptors first,
// then add non-conflicting properties from rest
const result = {} as any;
Object.defineProperties(result, Object.getOwnPropertyDescriptors(lazyProps));
const restDescriptors = Object.getOwnPropertyDescriptors(rest);
for (const key in restDescriptors) {
if (!Object.prototype.hasOwnProperty.call(result, key)) {
Object.defineProperty(result, key, restDescriptors[key]);
}
}
result.children = children;
result.render = render;
return React.createElement(component, result);
}
if (render) {
const result = {} as T;
Object.defineProperties(
result,
Object.getOwnPropertyDescriptors(lazyProps),
);
// Only add properties from rest that don't already exist
const restDescriptors = Object.getOwnPropertyDescriptors(rest);
for (const key in restDescriptors) {
if (!Object.prototype.hasOwnProperty.call(result as any, key)) {
Object.defineProperty(result as any, key, restDescriptors[key]);
}
}
if (children !== undefined) {
(result as any).children = children;
}
return render(result);
}
if (typeof children !== "function") {
throw new Error(
`Must specify either a render prop, a render function as children, or a component prop to ${name}`,
);
}
const result = {} as T;
Object.defineProperties(result, Object.getOwnPropertyDescriptors(lazyProps));
// Only add properties from rest that don't already exist
const restDescriptors = Object.getOwnPropertyDescriptors(rest);
for (const key in restDescriptors) {
if (!Object.prototype.hasOwnProperty.call(result as any, key)) {
Object.defineProperty(result as any, key, restDescriptors[key]);
}
}
return children(result);
}