Skip to content

Commit

Permalink
Refactor/rax compat (alibaba#6493)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
wssgcg1213 authored Sep 11, 2023
1 parent 42718fd commit b70bba1
Show file tree
Hide file tree
Showing 5 changed files with 445 additions and 26 deletions.
6 changes: 6 additions & 0 deletions .changeset/grumpy-garlics-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'rax-compat': patch
---

1. update @swc/helpers version to latest.
2. relplace create react class with simple impl.
8 changes: 4 additions & 4 deletions packages/rax-compat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@
"compat"
],
"dependencies": {
"@swc/helpers": "^0.4.3",
"style-unit": "^3.0.5",
"create-react-class": "^15.7.0",
"@ice/appear": "^0.2.0"
"@ice/appear": "^0.2.0",
"@swc/helpers": "^0.5.1",
"style-unit": "^3.0.5"
},
"devDependencies": {
"@ice/pkg": "^1.5.0",
"@types/rax": "^1.0.8",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"prop-types": "^15.8.1",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
Expand Down
130 changes: 127 additions & 3 deletions packages/rax-compat/src/create-class.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,129 @@
import createReactClass from 'create-react-class';

// See https://github.com/alibaba/rax/blob/master/packages/rax-create-class/src/index.js
// Imported by 'rax-compat/createReactClass'
export default createReactClass;
import type { ComponentSpec, ClassicComponentClass } from 'react';
import { Component } from 'react';

const AUTOBIND_BLACKLIST = {
render: 1,
shouldComponentUpdate: 1,
componentWillReceiveProps: 1,
componentWillUpdate: 1,
componentDidUpdate: 1,
componentWillMount: 1,
componentDidMount: 1,
componentWillUnmount: 1,
componentDidUnmount: 1,
};

function collateMixins(mixins: any) {
let keyed: Record<string, any> = {};

for (let i = 0; i < mixins.length; i++) {
let mixin = mixins[i];
if (mixin.mixins) {
applyMixins(mixin, collateMixins(mixin.mixins));
}

for (let key in mixin) {
if (mixin.hasOwnProperty(key) && key !== 'mixins') {

Check warning on line 28 in packages/rax-compat/src/create-class.ts

View workflow job for this annotation

GitHub Actions / build (16.x, ubuntu-latest)

Do not access Object.prototype method 'hasOwnProperty' from target object

Check warning on line 28 in packages/rax-compat/src/create-class.ts

View workflow job for this annotation

GitHub Actions / build (16.x, windows-latest)

Do not access Object.prototype method 'hasOwnProperty' from target object

Check warning on line 28 in packages/rax-compat/src/create-class.ts

View workflow job for this annotation

GitHub Actions / build (18.x, ubuntu-latest)

Do not access Object.prototype method 'hasOwnProperty' from target object

Check warning on line 28 in packages/rax-compat/src/create-class.ts

View workflow job for this annotation

GitHub Actions / build (18.x, windows-latest)

Do not access Object.prototype method 'hasOwnProperty' from target object
(keyed[key] || (keyed[key] = [])).push(mixin[key]);
}
}
}

return keyed;
}

function flattenHooks(key: string, hooks: Array<any>) {
let hookType = typeof hooks[0];
// Consider "null" value.
if (hooks[0] && hookType === 'object') {
// Merge objects in hooks
hooks.unshift({});
return Object.assign.apply(null, hooks);
} else if (hookType === 'function' && (key === 'getInitialState' || key === 'getDefaultProps' || key === 'getChildContext')) {
return function () {
let ret;
for (let i = 0; i < hooks.length; i++) {
// @ts-ignore
let r = hooks[i].apply(this, arguments);

Check warning on line 49 in packages/rax-compat/src/create-class.ts

View workflow job for this annotation

GitHub Actions / build (16.x, ubuntu-latest)

Use the rest parameters instead of 'arguments'

Check warning on line 49 in packages/rax-compat/src/create-class.ts

View workflow job for this annotation

GitHub Actions / build (16.x, windows-latest)

Use the rest parameters instead of 'arguments'

Check warning on line 49 in packages/rax-compat/src/create-class.ts

View workflow job for this annotation

GitHub Actions / build (18.x, ubuntu-latest)

Use the rest parameters instead of 'arguments'

Check warning on line 49 in packages/rax-compat/src/create-class.ts

View workflow job for this annotation

GitHub Actions / build (18.x, windows-latest)

Use the rest parameters instead of 'arguments'
if (r) {
if (!ret) ret = {};
Object.assign(ret, r);
}
}
return ret;
};
} else {
return hooks[0];
}
}
function applyMixins(proto: any, mixins: Record<string, any>) {
for (let key in mixins) {
// eslint-disable-next-line no-prototype-builtins
if (mixins.hasOwnProperty(key)) {
proto[key] = flattenHooks(key, mixins[key].concat(proto[key] || []));
}
}
}

function createReactClass<P, S = {}>(spec: ComponentSpec<P, S>): ClassicComponentClass<P> {
class ReactClass extends Component<P, S> {
constructor(props: P, context: any) {
super(props, context);

for (let methodName in this) {
let method = this[methodName];
// @ts-ignore
if (typeof method === 'function' && !AUTOBIND_BLACKLIST[methodName]) {
this[methodName] = method.bind(this);
}
}

if (spec.getInitialState) {
this.state = spec.getInitialState.call(this);
}
}
}

if (spec.mixins) {
applyMixins(spec, collateMixins(spec.mixins));
}

// Not to pass contextTypes to prototype.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { propTypes, contextTypes, ...others } = spec;
Object.assign(ReactClass.prototype, others);

if (spec.statics) {
Object.assign(ReactClass, spec.statics);
}

if (spec.propTypes) {
// @ts-ignore
ReactClass.propTypes = spec.propTypes;
}

if (spec.getDefaultProps) {
// @ts-ignore
ReactClass.defaultProps = spec.getDefaultProps();
}

if (spec.contextTypes) {
// @ts-ignore
ReactClass.contextTypes = spec.contextTypes;
}

if (spec.childContextTypes) {
// @ts-ignore
ReactClass.childContextTypes = spec.childContextTypes;
}

if (spec.displayName) {
// @ts-ignore
ReactClass.displayName = spec.displayName;
}

return ReactClass as ClassicComponentClass<P>;
}
export default createReactClass;
Loading

0 comments on commit b70bba1

Please sign in to comment.