living-together/source/Context/Context.tsx
2022-04-15 22:51:38 +08:00

78 lines
2.0 KiB
TypeScript

import { Component, FunctionComponent, ReactNode, Consumer } from "react";
import { Emitter, EventType } from "@Model/Emitter";
type RenderComponent = (new (...p: any) => Component<any, any, any>) | FunctionComponent<any>;
function superConnectWithEvent<C extends Emitter<E>, E extends Record<EventType, any>>(
consumer: Consumer<C>, keyName: string
) {
return (...events: Array<keyof E>) => {
return <R extends RenderComponent>(components: R): R => {
const Components = components as any;
const Consumer = consumer;
return class extends Component<R> {
private status: C | undefined;
private isEventMount: boolean = false;
private propsObject: Record<string, C> = {};
private handelChange = () => {
this.forceUpdate();
}
private mountEvent() {
if (this.status && !this.isEventMount) {
this.isEventMount = true;
console.log("Component dep event mount: " + events.join(", "));
for (let i = 0; i < events.length; i++) {
this.status.on(events[i], this.handelChange);
}
}
}
private unmountEvent() {
if (this.status) {
for (let i = 0; i < events.length; i++) {
this.status.off(events[i], this.handelChange);
}
}
}
public render(): ReactNode {
return <Consumer>
{(status: C) => {
this.status = status;
this.propsObject[keyName] = status;
this.mountEvent();
return <Components {...this.props} {...this.propsObject}/>;
}}
</Consumer>
}
public componentWillUnmount() {
this.unmountEvent();
}
} as any;
}
}
}
function superConnect<C>(consumer: Consumer<C>, keyName: string) {
return <R extends RenderComponent>(components: R): R => {
return ((props: any) => {
const Components = components as any;
const Consumer = consumer;
return <Consumer>
{(status: C) => <Components
{...props}
{...{[keyName]: status}}
/>}
</Consumer>
}) as any;
}
}
export { superConnectWithEvent, superConnect };