Skip to content

Commit 682e12d

Browse files
committed
div should be ok
1 parent cff5a6f commit 682e12d

12 files changed

+353
-45
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"dependencies": {
4141
"@types/react": "^18.0.6",
4242
"@types/react-dom": "^18.0.2",
43+
"@types/react-reconciler": "^0.26.6",
4344
"react": "^18.0.0",
4445
"react-dom": "^18.0.0",
4546
"react-reconciler": "^0.27.0"

src/common/types.ts

+18
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@ import type { ComponentContextValue } from './ComponentContext';
33

44
export interface WorkerRenderComponent extends React.Component<any, any> {
55
id: string;
6+
componentName: string;
67
componentContext?: ComponentContextValue;
78
componentChildIndex: number;
89
componentChildIndexMap: Map<WorkerRenderComponent, number>;
910
componentIndex: number;
1011
componentPath: string;
1112
componentSpec: WorkerRenderComponentSpec;
13+
callMethod(method: string, args: any[]): void;
1214
}
1315
export type ComponentPath = string;
1416
export type ComponentId = string;
1517

1618
export interface AppComponent extends WorkerRenderComponent {
19+
postMessage(msg: any): void;
20+
componentNameDefaultPropsMap: Record<string, string>;
1721
newComponentsPathIdMap: Record<ComponentPath, ComponentId>;
1822
newComponentsIdStateMap: Record<ComponentId, any>;
1923
addComponent(component: WorkerRenderComponent): void;
@@ -25,6 +29,7 @@ export interface WorkerRenderComponentSpec
2529
extends React.ComponentLifecycle<any, any>,
2630
React.StaticLifecycle<any, any> {
2731
getInitialState?: () => any;
32+
defaultProps?: any;
2833
render: (args: {
2934
native: Record<string, React.ComponentClass>;
3035
props: any;
@@ -39,3 +44,16 @@ export interface MessageChannel {
3944
postMessage(msg: string): void;
4045
onMessage(msg: string): void;
4146
}
47+
48+
export interface FromWorkerMsg {
49+
newComponentNameDefaultPropsMap: Record<string, string>;
50+
pendingIdStateMap: Record<string, string>;
51+
newComponentsPathIdMap: Record<string, string>;
52+
newComponentsIdStateMap: Record<string, string>;
53+
}
54+
55+
export interface FromRenderMsg {
56+
componentId: string;
57+
method: string;
58+
args: any[];
59+
}

src/render/App.tsx

+71-17
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import componentPath from '../common/componentPath';
22
import React from 'react';
33
import { getComponentDesc } from '../common/register';
4-
import { AppComponent, WorkerRenderComponent } from '../common/types';
4+
import {
5+
AppComponent,
6+
WorkerRenderComponent,
7+
MessageChannel,
8+
FromWorkerMsg,
9+
FromRenderMsg,
10+
} from '../common/types';
511
import { nativeComponents } from './nativeComponentClass';
612
import { getComponentClass } from './getComponentClass';
13+
import ReactDOM from 'react-dom';
14+
715
class App
8-
extends React.Component<{ channel: MessageChannel }>
16+
extends React.Component<{ channel: MessageChannel }, { inited: boolean }>
917
implements AppComponent
1018
{
1119
id: string;
@@ -14,17 +22,62 @@ class App
1422
componentChildIndex = 0;
1523
componentChildIndexMap = new Map();
1624
newComponentsPathIdMap = {};
25+
componentNameDefaultPropsMap = {};
1726
newComponentsIdStateMap = {};
1827
pendingIdStateMap = {};
1928
components: Map<string, WorkerRenderComponent> = new Map();
2029
nativeEventHandles: Record<string, () => void>;
2130
componentSpec = null!;
31+
componentName = '';
2232

2333
constructor(props: any) {
2434
super(props);
2535
this.nativeEventHandles = {};
2636
this.id = '1';
2737
this.addComponent(this);
38+
this.props.channel.onMessage = this.onMessage;
39+
this.state = {
40+
inited: false,
41+
};
42+
}
43+
onMessage = (e: any) => {
44+
const msg: FromWorkerMsg = JSON.parse(e.data);
45+
const {
46+
newComponentsIdStateMap,
47+
newComponentsPathIdMap,
48+
pendingIdStateMap,
49+
newComponentNameDefaultPropsMap,
50+
} = msg;
51+
const { components, componentNameDefaultPropsMap } = this;
52+
Object.assign(
53+
componentNameDefaultPropsMap,
54+
newComponentNameDefaultPropsMap,
55+
);
56+
for (const name of Object.keys(newComponentNameDefaultPropsMap)) {
57+
getComponentClass(name).defaultProps =
58+
newComponentNameDefaultPropsMap[name];
59+
}
60+
this.newComponentsIdStateMap = newComponentsIdStateMap;
61+
this.newComponentsPathIdMap = newComponentsPathIdMap;
62+
63+
ReactDOM.unstable_batchedUpdates(() => {
64+
if (!this.state.inited) {
65+
this.setState({
66+
inited: true,
67+
});
68+
}
69+
for (const id of Object.keys(pendingIdStateMap)) {
70+
const state = pendingIdStateMap[id];
71+
const component = components.get(id)!;
72+
component.setState(state);
73+
}
74+
});
75+
};
76+
postMessage(msg: FromRenderMsg) {
77+
this.props.channel.postMessage(JSON.stringify(msg));
78+
}
79+
callMethod() {
80+
return;
2881
}
2982
addComponent(component: WorkerRenderComponent) {
3083
this.components.set(component.id, component);
@@ -33,28 +86,29 @@ class App
3386
this.components.delete(component.id);
3487
}
3588
getNativeEventHandle = (name: string) => {
36-
const { nativeEventHandles } = this;
37-
if (nativeEventHandles[name]) {
38-
return nativeEventHandles[name];
39-
}
89+
return name;
4090
};
4191
getComponentEventHandle = (name: string) => {
4292
return name;
4393
};
4494
setStateState() {
4595
return;
4696
}
47-
render(): JSX.Element {
48-
const componentDesc = getComponentDesc('main');
49-
const element = componentDesc.render({
50-
native: nativeComponents,
51-
props: {},
52-
state: {},
53-
getNativeEventHandle: this.getNativeEventHandle,
54-
getComponentEventHandle: this.getComponentEventHandle,
55-
getComponentClass: getComponentClass,
56-
});
57-
return componentPath.renderWithComponentContext(this, element);
97+
render(): React.ReactNode {
98+
if (this.state.inited) {
99+
const componentDesc = getComponentDesc('main');
100+
const element = componentDesc.render({
101+
native: nativeComponents,
102+
props: {},
103+
state: {},
104+
getNativeEventHandle: this.getNativeEventHandle,
105+
getComponentEventHandle: this.getComponentEventHandle,
106+
getComponentClass: getComponentClass,
107+
});
108+
return componentPath.renderWithComponentContext(this, element);
109+
} else {
110+
return null;
111+
}
58112
}
59113
}
60114

src/render/getComponentClass.tsx

+47-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import { getComponentDesc } from '../common/register';
3-
import { WorkerRenderComponent } from '../common/types';
3+
import { FromRenderMsg, WorkerRenderComponent } from '../common/types';
44
import { nativeComponents } from './nativeComponentClass';
55
import componentPath from '../common/componentPath';
66
import ComponentContext, {
@@ -9,8 +9,6 @@ import ComponentContext, {
99

1010
const componentClassCache: Record<string, React.ComponentClass> = {};
1111

12-
let gid = 1;
13-
1412
export function getComponentClass(name: string): React.ComponentClass {
1513
if (componentClassCache[name]) {
1614
return componentClassCache[name];
@@ -22,65 +20,98 @@ export function getComponentClass(name: string): React.ComponentClass {
2220
extends React.Component<any, { state: any; __self: Component }>
2321
implements WorkerRenderComponent
2422
{
25-
id: string;
2623
componentIndex = 0;
2724
componentPath = '';
2825
componentChildIndex = 0;
2926
componentChildIndexMap = new Map();
30-
nativeEventHandles: Record<string, () => void>;
27+
nativeEventHandles: Record<string, () => void> = {};
3128
componentSpec = componentSpec;
32-
29+
componentName = name;
3330
static contextType = ComponentContext;
34-
31+
publicInstance: any = {};
32+
id = '';
3533
constructor(props: any) {
3634
super(props);
37-
this.id = ++gid + '';
38-
this.nativeEventHandles = {};
3935
this.state = {
4036
__self: this,
4137
state: {},
4238
};
39+
Object.defineProperty(this.publicInstance, 'props', {
40+
get: () => {
41+
return this.props;
42+
},
43+
});
44+
Object.defineProperty(this.publicInstance, 'state', {
45+
get: () => {
46+
return this.state.state;
47+
},
48+
});
49+
}
50+
callMethod() {
51+
return;
4352
}
44-
4553
static getDerivedStateFromProps(_: any, { __self }: any) {
4654
const instance: Component = __self;
4755
componentPath.updateComponentPath(instance);
4856
let state;
4957
const { app } = instance.context as ComponentContextValue;
50-
if (instance.id) {
51-
state = instance.state.state;
52-
} else {
58+
if (!instance.id) {
5359
const path = componentPath.getComponentPath(instance);
5460
instance.id = app.newComponentsPathIdMap[path];
5561
if (!instance.id) {
5662
throw new Error(`Can not find id from path: ${path}`);
5763
}
5864
app.addComponent(instance);
59-
state = app.newComponentsIdStateMap[instance.id];
65+
state = app.newComponentsIdStateMap[instance.id] || {};
66+
return { state };
6067
}
61-
return { state };
68+
return {};
6269
}
6370

6471
getContext() {
6572
return this.context as ComponentContextValue;
6673
}
6774

75+
componentDidMount() {
76+
componentSpec.componentDidMount?.call(this.publicInstance);
77+
}
78+
79+
componentDidUpdate(prevProps: any, prevState: any) {
80+
const { publicInstance } = this;
81+
componentSpec.componentDidUpdate?.call(
82+
publicInstance,
83+
prevProps,
84+
prevState.state,
85+
);
86+
}
87+
6888
componentWillUnmount() {
89+
componentSpec.componentWillUnmount?.call(this.publicInstance);
6990
this.getContext().app.removeComponent(this);
7091
}
7192

7293
getNativeEventHandle = (name: string) => {
7394
const { nativeEventHandles } = this;
95+
const { app } = this.context as ComponentContextValue;
7496
if (nativeEventHandles[name]) {
7597
return nativeEventHandles[name];
7698
}
99+
nativeEventHandles[name] = (...args: any) => {
100+
const msg: FromRenderMsg = {
101+
componentId: this.id,
102+
method: name,
103+
args,
104+
};
105+
app.postMessage(msg);
106+
};
107+
return nativeEventHandles[name];
77108
};
78109

79110
getComponentEventHandle = (name: string) => {
80111
return name;
81112
};
82113

83-
render(): JSX.Element {
114+
render(): React.ReactNode {
84115
const element = componentSpec.render({
85116
native: nativeComponents,
86117
props: this.props,

src/render/index.ts

-1
This file was deleted.

src/render/index.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { registerComponent } from '../common/register';
2+
import App from './App';
3+
export { registerComponent, App };

0 commit comments

Comments
 (0)