Skip to content

Commit b70bba1

Browse files
authored
Refactor/rax compat (#6493)
* refactor: rax compat 1. update @swc/helpers version to latest. 2. relplace create react class with simple impl. * test: add specs for createReactClass * chore: rename to createReactClass
1 parent 42718fd commit b70bba1

File tree

5 files changed

+445
-26
lines changed

5 files changed

+445
-26
lines changed

.changeset/grumpy-garlics-agree.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'rax-compat': patch
3+
---
4+
5+
1. update @swc/helpers version to latest.
6+
2. relplace create react class with simple impl.

packages/rax-compat/package.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@
4848
"compat"
4949
],
5050
"dependencies": {
51-
"@swc/helpers": "^0.4.3",
52-
"style-unit": "^3.0.5",
53-
"create-react-class": "^15.7.0",
54-
"@ice/appear": "^0.2.0"
51+
"@ice/appear": "^0.2.0",
52+
"@swc/helpers": "^0.5.1",
53+
"style-unit": "^3.0.5"
5554
},
5655
"devDependencies": {
5756
"@ice/pkg": "^1.5.0",
5857
"@types/rax": "^1.0.8",
5958
"@types/react": "^18.0.0",
6059
"@types/react-dom": "^18.0.0",
60+
"prop-types": "^15.8.1",
6161
"react": "^18.0.0",
6262
"react-dom": "^18.0.0"
6363
},
+127-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,129 @@
1-
import createReactClass from 'create-react-class';
2-
31
// See https://github.com/alibaba/rax/blob/master/packages/rax-create-class/src/index.js
42
// Imported by 'rax-compat/createReactClass'
5-
export default createReactClass;
3+
import type { ComponentSpec, ClassicComponentClass } from 'react';
4+
import { Component } from 'react';
5+
6+
const AUTOBIND_BLACKLIST = {
7+
render: 1,
8+
shouldComponentUpdate: 1,
9+
componentWillReceiveProps: 1,
10+
componentWillUpdate: 1,
11+
componentDidUpdate: 1,
12+
componentWillMount: 1,
13+
componentDidMount: 1,
14+
componentWillUnmount: 1,
15+
componentDidUnmount: 1,
16+
};
17+
18+
function collateMixins(mixins: any) {
19+
let keyed: Record<string, any> = {};
20+
21+
for (let i = 0; i < mixins.length; i++) {
22+
let mixin = mixins[i];
23+
if (mixin.mixins) {
24+
applyMixins(mixin, collateMixins(mixin.mixins));
25+
}
26+
27+
for (let key in mixin) {
28+
if (mixin.hasOwnProperty(key) && key !== 'mixins') {
29+
(keyed[key] || (keyed[key] = [])).push(mixin[key]);
30+
}
31+
}
32+
}
33+
34+
return keyed;
35+
}
36+
37+
function flattenHooks(key: string, hooks: Array<any>) {
38+
let hookType = typeof hooks[0];
39+
// Consider "null" value.
40+
if (hooks[0] && hookType === 'object') {
41+
// Merge objects in hooks
42+
hooks.unshift({});
43+
return Object.assign.apply(null, hooks);
44+
} else if (hookType === 'function' && (key === 'getInitialState' || key === 'getDefaultProps' || key === 'getChildContext')) {
45+
return function () {
46+
let ret;
47+
for (let i = 0; i < hooks.length; i++) {
48+
// @ts-ignore
49+
let r = hooks[i].apply(this, arguments);
50+
if (r) {
51+
if (!ret) ret = {};
52+
Object.assign(ret, r);
53+
}
54+
}
55+
return ret;
56+
};
57+
} else {
58+
return hooks[0];
59+
}
60+
}
61+
function applyMixins(proto: any, mixins: Record<string, any>) {
62+
for (let key in mixins) {
63+
// eslint-disable-next-line no-prototype-builtins
64+
if (mixins.hasOwnProperty(key)) {
65+
proto[key] = flattenHooks(key, mixins[key].concat(proto[key] || []));
66+
}
67+
}
68+
}
69+
70+
function createReactClass<P, S = {}>(spec: ComponentSpec<P, S>): ClassicComponentClass<P> {
71+
class ReactClass extends Component<P, S> {
72+
constructor(props: P, context: any) {
73+
super(props, context);
74+
75+
for (let methodName in this) {
76+
let method = this[methodName];
77+
// @ts-ignore
78+
if (typeof method === 'function' && !AUTOBIND_BLACKLIST[methodName]) {
79+
this[methodName] = method.bind(this);
80+
}
81+
}
82+
83+
if (spec.getInitialState) {
84+
this.state = spec.getInitialState.call(this);
85+
}
86+
}
87+
}
88+
89+
if (spec.mixins) {
90+
applyMixins(spec, collateMixins(spec.mixins));
91+
}
92+
93+
// Not to pass contextTypes to prototype.
94+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
95+
const { propTypes, contextTypes, ...others } = spec;
96+
Object.assign(ReactClass.prototype, others);
97+
98+
if (spec.statics) {
99+
Object.assign(ReactClass, spec.statics);
100+
}
101+
102+
if (spec.propTypes) {
103+
// @ts-ignore
104+
ReactClass.propTypes = spec.propTypes;
105+
}
106+
107+
if (spec.getDefaultProps) {
108+
// @ts-ignore
109+
ReactClass.defaultProps = spec.getDefaultProps();
110+
}
111+
112+
if (spec.contextTypes) {
113+
// @ts-ignore
114+
ReactClass.contextTypes = spec.contextTypes;
115+
}
116+
117+
if (spec.childContextTypes) {
118+
// @ts-ignore
119+
ReactClass.childContextTypes = spec.childContextTypes;
120+
}
121+
122+
if (spec.displayName) {
123+
// @ts-ignore
124+
ReactClass.displayName = spec.displayName;
125+
}
126+
127+
return ReactClass as ClassicComponentClass<P>;
128+
}
129+
export default createReactClass;

0 commit comments

Comments
 (0)