-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: extract react service, and re render by observable model
- Loading branch information
Showing
3 changed files
with
65 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { BaseService } from 'mo/services/baseService'; | ||
|
||
export abstract class Component<S> extends BaseService { | ||
protected abstract state: S; | ||
|
||
public updateState(nextState: S) { | ||
Object.assign(this.state, nextState); | ||
} | ||
|
||
public getState(): S { | ||
return this.state; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './component'; | ||
export * from './mapState'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import * as React from 'react'; | ||
import Logger from 'mo/common/logger'; | ||
|
||
/** | ||
* Mapping the state to the component | ||
* @param WrappedComponent The component will be wrapped | ||
* @param state The state you want to injected, notice the state must be an observable object | ||
* @param subscribes The events of your subscribe, it used to trigger the state re render | ||
*/ | ||
export function mapState<S>(WrappedComponent: React.ComponentType<S>, state: S) { | ||
return class StateProvider extends React.Component { | ||
state: { lastUpdated: number }; | ||
constructor(props) { | ||
super(props); | ||
this.onChange = this.onChange.bind(this); | ||
this.state = { | ||
lastUpdated: Date.now(), | ||
}; | ||
} | ||
|
||
_count = 0; | ||
|
||
componentDidMount() { | ||
// There is no declare state argument as IObservable type, so must convert to any type. | ||
if ((state as any).observe) { | ||
console.log('mapState:', this._count++); | ||
(state as any).observe(this.onChange); | ||
} else { | ||
Logger.error('The state argument of mapState must be an observable object.'); | ||
} | ||
} | ||
/** | ||
* TODO: Performance optimize, now whatever any properties changed in target, | ||
* there always be trigger the onChange event, so need a compare operation. | ||
* @param nextState changed data | ||
*/ | ||
onChange(nextState: S) { | ||
Logger.info(nextState, state); | ||
this.setState({ | ||
lastUpdated: Date.now(), | ||
}); | ||
} | ||
|
||
render() { | ||
return ( | ||
<WrappedComponent {...this.state} { ...state} {...this.props} /> | ||
); | ||
} | ||
}; | ||
} |