core-native
Version:
A lightweight framework based on React Native + Redux + Redux Saga, in strict TypeScript.
110 lines • 5.29 kB
JavaScript
import React from "react";
import { AppState } from "react-native";
import { delay, put } from "redux-saga/effects";
import { app } from "../app";
import { errorAction, setStateAction } from "../reducer";
export class ModuleProxy {
constructor(module, actions) {
this.module = module;
this.actions = actions;
}
getActions() {
return this.actions;
}
attachLifecycle(ComponentType) {
var _a;
const moduleName = this.module.name;
const initialState = this.module.initialState;
const lifecycleListener = this.module;
const actions = this.actions;
return _a = class MainComponent extends React.PureComponent {
constructor(props) {
super(props);
this.onAppStateChange = (nextAppState) => {
const { appState } = this.state;
if (["inactive", "background"].includes(appState) && nextAppState === "active") {
if (lifecycleListener.onAppActive.isLifecycle) {
app.store.dispatch(actions.onAppActive());
}
}
else if (appState === "active" && ["inactive", "background"].includes(nextAppState)) {
if (lifecycleListener.onAppInactive.isLifecycle) {
app.store.dispatch(actions.onAppInactive());
}
}
this.setState({ appState: nextAppState });
};
this.state = { appState: AppState.currentState };
this.lifecycleSagaTask = app.sagaMiddleware.run(this.lifecycleSaga.bind(this));
console.info(`Module [${moduleName}] attached component initially rendered`);
}
componentDidMount() {
// According to the document, this API may change soon
// Ref: https://facebook.github.io/react-native/docs/appstate#addeventlistener
AppState.addEventListener("change", this.onAppStateChange);
const props = this.props;
if ("navigation" in props) {
const navigation = props.navigation;
this.focusSubscription = navigation.addListener("didFocus", () => {
if (lifecycleListener.onFocus.isLifecycle) {
app.store.dispatch(actions.onFocus());
}
});
this.blurSubscription = navigation.addListener("willBlur", () => {
if (lifecycleListener.onBlur.isLifecycle) {
app.store.dispatch(actions.onBlur());
}
});
}
}
componentWillUnmount() {
if (lifecycleListener.onDestroy.isLifecycle) {
app.store.dispatch(actions.onDestroy());
}
if (this.blurSubscription) {
this.blurSubscription.remove();
}
if (this.focusSubscription) {
this.focusSubscription.remove();
}
this.lifecycleSagaTask.cancel();
app.store.dispatch(setStateAction(moduleName, initialState, `@@${moduleName}/@`));
AppState.removeEventListener("change", this.onAppStateChange);
console.info(`Module [${moduleName}] attached component destroyed`);
}
*lifecycleSaga() {
const props = this.props;
if (lifecycleListener.onEnter.isLifecycle) {
if ("navigation" in props && "state" in props.navigation) {
yield* runSafely(lifecycleListener.onEnter.bind(lifecycleListener), props.navigation.state.params, props.navigation.state.path);
}
else {
yield* runSafely(lifecycleListener.onEnter.bind(lifecycleListener), {}, null);
}
}
if (lifecycleListener.onTick.isLifecycle) {
const tickIntervalInMillisecond = (lifecycleListener.onTick.tickInterval || 5) * 1000;
const boundTicker = lifecycleListener.onTick.bind(lifecycleListener);
while (true) {
yield* runSafely(boundTicker);
yield delay(tickIntervalInMillisecond);
}
}
}
render() {
return <ComponentType {...this.props}/>;
}
},
_a.displayName = `ModuleBoundary(${moduleName})`,
_a;
}
}
function* runSafely(handler, ...payload) {
try {
yield* handler(...payload);
}
catch (error) {
yield put(errorAction(error));
}
}
//# sourceMappingURL=ModuleProxy.js.map