Skip to content

Commit 2686c38

Browse files
committed
add input
1 parent 682e12d commit 2686c38

13 files changed

+212
-100
lines changed

package.json

+2-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"type": "git",
99
"url": "git@github.com:yiminghe/react-worker-render.git"
1010
},
11-
"main": "src/index.ts",
11+
"files": ["lib"],
12+
"main": "lib/index",
1213
"scripts": {
1314
"lint-fix": "yarn run lint --fix",
1415
"lint": "yarn run eslint . --ext .ts",
@@ -30,9 +31,6 @@
3031
"eslint": "^8.11.0",
3132
"eslint-config-prettier": "^8.5.0",
3233
"fs-extra": "^10.0.1",
33-
"pika-plugin-build-web-babel": "^0.11.2",
34-
"pika-plugin-clean-dist-src": "^0.1.1",
35-
"pika-plugin-ts-types": "^0.1.5",
3634
"prettier": "2.x",
3735
"typescript": "^4.6.2"
3836
},

src/common/ComponentContext.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import React from 'react';
2-
import type { AppComponent, WorkerRenderComponent } from './types';
2+
import type {
3+
AppComponent,
4+
ComponentPathMeta,
5+
WorkerRenderComponent,
6+
} from './types';
37

48
export type ComponentContextValue = {
5-
parent: WorkerRenderComponent;
9+
parent: ComponentPathMeta;
610
app: AppComponent;
711
};
812

src/common/componentPath.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import ComponentContext, { ComponentContextValue } from './ComponentContext';
22
import React from 'react';
3-
import { WorkerRenderComponent } from './types';
3+
import { ComponentPathMeta } from './types';
44

5-
function getComponentContext(instance: WorkerRenderComponent) {
5+
function getComponentContext(instance: ComponentPathMeta) {
66
if (!instance.componentContext) {
77
instance.componentContext = {
88
parent: instance,
@@ -18,7 +18,7 @@ const componentPath = {
1818
ComponentClass.contextType = ComponentContext;
1919
},
2020

21-
updateComponentPath(instance: WorkerRenderComponent) {
21+
updateComponentPath(instance: ComponentPathMeta) {
2222
const { parent } = instance.context as ComponentContextValue;
2323
const { componentChildIndexMap } = parent;
2424
if (componentChildIndexMap.has(instance)) {
@@ -30,7 +30,7 @@ const componentPath = {
3030
}
3131
},
3232

33-
getComponentPath(instance: WorkerRenderComponent) {
33+
getComponentPath(instance: ComponentPathMeta) {
3434
if (!instance.componentPath) {
3535
const { parent } = instance.context as ComponentContextValue;
3636
instance.componentPath = `${componentPath.getComponentPath(parent)}-${
@@ -41,7 +41,7 @@ const componentPath = {
4141
},
4242

4343
renderWithComponentContext(
44-
instance: WorkerRenderComponent,
44+
instance: ComponentPathMeta,
4545
element: React.ReactNode,
4646
) {
4747
instance.componentChildIndex = 0;

src/common/types.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11
import React from 'react';
22
import type { ComponentContextValue } from './ComponentContext';
33

4-
export interface WorkerRenderComponent extends React.Component<any, any> {
5-
id: string;
6-
componentName: string;
4+
export interface ComponentPathMeta<P = any, S = any>
5+
extends React.Component<P, S> {
76
componentContext?: ComponentContextValue;
87
componentChildIndex: number;
9-
componentChildIndexMap: Map<WorkerRenderComponent, number>;
8+
componentChildIndexMap: Map<ComponentPathMeta, number>;
109
componentIndex: number;
1110
componentPath: string;
11+
}
12+
13+
export interface WorkerRenderComponent<P = any, S = any>
14+
extends ComponentPathMeta<P, S> {
15+
id: string;
16+
componentName: string;
17+
getInstanceState(): any;
18+
getInstanceProps(): any;
1219
componentSpec: WorkerRenderComponentSpec;
1320
callMethod(method: string, args: any[]): void;
1421
}
1522
export type ComponentPath = string;
1623
export type ComponentId = string;
1724

18-
export interface AppComponent extends WorkerRenderComponent {
25+
export interface AppComponent<P = any, S = any>
26+
extends ComponentPathMeta<P, S> {
1927
postMessage(msg: any): void;
2028
componentNameDefaultPropsMap: Record<string, string>;
2129
newComponentsPathIdMap: Record<ComponentPath, ComponentId>;
@@ -30,14 +38,15 @@ export interface WorkerRenderComponentSpec
3038
React.StaticLifecycle<any, any> {
3139
getInitialState?: () => any;
3240
defaultProps?: any;
33-
render: (args: {
41+
render: (this: {
3442
native: Record<string, React.ComponentClass>;
3543
props: any;
3644
state: any;
37-
getComponentClass: (name: string) => React.ComponentClass;
45+
getComponent: (name: string) => React.ComponentClass;
3846
getNativeEventHandle: (name: string) => any;
3947
getComponentEventHandle: (name: string) => any;
4048
}) => React.ReactNode;
49+
[k: string]: any;
4150
}
4251

4352
export interface MessageChannel {

src/common/utils.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export function noop() {
2+
return;
3+
}
4+
5+
export function cleanFuncJson(json: any) {
6+
const ret: any = {};
7+
for (const k of Object.keys(json)) {
8+
const value = json[k];
9+
if (typeof value !== 'function') {
10+
ret[k] = value;
11+
continue;
12+
}
13+
if (k.match(/^on[A-z]/)) {
14+
ret[k] = value.handleName + '';
15+
}
16+
}
17+
return ret;
18+
}

src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export * from './worker/';
2-
export * from './render/';
1+
export * as ReactWorker from './worker/';
2+
export * as ReactRender from './render/';

src/render/App.tsx

+9-22
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import {
1111
import { nativeComponents } from './nativeComponentClass';
1212
import { getComponentClass } from './getComponentClass';
1313
import ReactDOM from 'react-dom';
14+
import { noop } from '../common/utils';
1415

1516
class App
1617
extends React.Component<{ channel: MessageChannel }, { inited: boolean }>
1718
implements AppComponent
1819
{
19-
id: string;
2020
componentIndex = 0;
2121
componentPath = '1';
2222
componentChildIndex = 0;
@@ -26,15 +26,10 @@ class App
2626
newComponentsIdStateMap = {};
2727
pendingIdStateMap = {};
2828
components: Map<string, WorkerRenderComponent> = new Map();
29-
nativeEventHandles: Record<string, () => void>;
3029
componentSpec = null!;
31-
componentName = '';
3230

3331
constructor(props: any) {
3432
super(props);
35-
this.nativeEventHandles = {};
36-
this.id = '1';
37-
this.addComponent(this);
3833
this.props.channel.onMessage = this.onMessage;
3934
this.state = {
4035
inited: false,
@@ -76,34 +71,26 @@ class App
7671
postMessage(msg: FromRenderMsg) {
7772
this.props.channel.postMessage(JSON.stringify(msg));
7873
}
79-
callMethod() {
80-
return;
81-
}
74+
8275
addComponent(component: WorkerRenderComponent) {
8376
this.components.set(component.id, component);
8477
}
8578
removeComponent(component: WorkerRenderComponent) {
8679
this.components.delete(component.id);
8780
}
88-
getNativeEventHandle = (name: string) => {
89-
return name;
90-
};
91-
getComponentEventHandle = (name: string) => {
92-
return name;
93-
};
94-
setStateState() {
95-
return;
96-
}
81+
82+
setStateState = noop;
83+
9784
render(): React.ReactNode {
9885
if (this.state.inited) {
9986
const componentDesc = getComponentDesc('main');
100-
const element = componentDesc.render({
87+
const element = componentDesc.render.call({
10188
native: nativeComponents,
10289
props: {},
10390
state: {},
104-
getNativeEventHandle: this.getNativeEventHandle,
105-
getComponentEventHandle: this.getComponentEventHandle,
106-
getComponentClass: getComponentClass,
91+
getNativeEventHandle: noop,
92+
getComponentEventHandle: noop,
93+
getComponent: getComponentClass,
10794
});
10895
return componentPath.renderWithComponentContext(this, element);
10996
} else {

src/render/getComponentClass.tsx

+19-11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import componentPath from '../common/componentPath';
66
import ComponentContext, {
77
ComponentContextValue,
88
} from '../common/ComponentContext';
9+
import Input from './native/Input';
10+
import { noop } from '../common/utils';
911

1012
const componentClassCache: Record<string, React.ComponentClass> = {};
1113

@@ -37,19 +39,12 @@ export function getComponentClass(name: string): React.ComponentClass {
3739
state: {},
3840
};
3941
Object.defineProperty(this.publicInstance, 'props', {
40-
get: () => {
41-
return this.props;
42-
},
42+
get: this.getInstanceProps,
4343
});
4444
Object.defineProperty(this.publicInstance, 'state', {
45-
get: () => {
46-
return this.state.state;
47-
},
45+
get: this.getInstanceState,
4846
});
4947
}
50-
callMethod() {
51-
return;
52-
}
5348
static getDerivedStateFromProps(_: any, { __self }: any) {
5449
const instance: Component = __self;
5550
componentPath.updateComponentPath(instance);
@@ -68,6 +63,12 @@ export function getComponentClass(name: string): React.ComponentClass {
6863
return {};
6964
}
7065

66+
getInstanceProps = () => {
67+
return this.props;
68+
};
69+
getInstanceState() {
70+
return this.state.state;
71+
}
7172
getContext() {
7273
return this.context as ComponentContextValue;
7374
}
@@ -76,6 +77,8 @@ export function getComponentClass(name: string): React.ComponentClass {
7677
componentSpec.componentDidMount?.call(this.publicInstance);
7778
}
7879

80+
callMethod = noop;
81+
7982
componentDidUpdate(prevProps: any, prevState: any) {
8083
const { publicInstance } = this;
8184
componentSpec.componentDidUpdate?.call(
@@ -104,6 +107,7 @@ export function getComponentClass(name: string): React.ComponentClass {
104107
};
105108
app.postMessage(msg);
106109
};
110+
(nativeEventHandles as any).handleName = name;
107111
return nativeEventHandles[name];
108112
};
109113

@@ -112,13 +116,13 @@ export function getComponentClass(name: string): React.ComponentClass {
112116
};
113117

114118
render(): React.ReactNode {
115-
const element = componentSpec.render({
119+
const element = componentSpec.render.call({
116120
native: nativeComponents,
117121
props: this.props,
118122
state: this.state.state,
119123
getNativeEventHandle: this.getNativeEventHandle,
120124
getComponentEventHandle: this.getComponentEventHandle,
121-
getComponentClass,
125+
getComponent: getComponentClass,
122126
});
123127
return componentPath.renderWithComponentContext(this, element);
124128
}
@@ -130,3 +134,7 @@ export function getComponentClass(name: string): React.ComponentClass {
130134
componentClassCache[name] = C;
131135
return C;
132136
}
137+
138+
Object.assign(nativeComponents, {
139+
input: (Input as any) || getComponentClass('input'),
140+
});

src/render/native/Input.tsx

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { registerComponent } from '../../worker';
2+
import React from 'react';
3+
4+
interface InputProps {
5+
value: string;
6+
seq: number;
7+
onChange: Function;
8+
}
9+
10+
interface InputState {
11+
value: string;
12+
seq: number;
13+
}
14+
15+
class Input extends React.Component<InputProps, InputState> {
16+
constructor(props: any) {
17+
super(props);
18+
this.state = {
19+
value: props.value,
20+
seq: props.seq || 1,
21+
};
22+
}
23+
getDerivedStateFromProps(nextProps: InputProps, prevState: InputState) {
24+
if (
25+
nextProps.seq === prevState.seq &&
26+
nextProps.value !== prevState.value
27+
) {
28+
return {
29+
...prevState,
30+
value: nextProps.value,
31+
};
32+
}
33+
}
34+
onChange = (e: any) => {
35+
const { value } = e;
36+
const current = {
37+
value,
38+
seq: this.state.seq + 1,
39+
};
40+
this.setState(current);
41+
this.props.onChange(current);
42+
};
43+
render() {
44+
return <input value={this.state.value} onChange={this.onChange}></input>;
45+
}
46+
}
47+
48+
export default registerComponent('input', {
49+
render() {
50+
return (
51+
<Input
52+
value={this.state.value}
53+
seq={this.state.seq}
54+
onChange={this.getNativeEventHandle('onChange')}
55+
/>
56+
);
57+
},
58+
});

0 commit comments

Comments
 (0)