Skip to content

Instantly share code, notes, and snippets.

@originalmoose
Created February 25, 2017 16:49
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save originalmoose/65ab88ad4930f731c6cd701d14eaeae3 to your computer and use it in GitHub Desktop.
Save originalmoose/65ab88ad4930f731c6cd701d14eaeae3 to your computer and use it in GitHub Desktop.
import * as React from "react";
import { observer } from "mobx-react";
import inject from "../store/Inject";
import { addTask } from "../module/task";
import { add, exists, fetch } from "../module/cache"
import { Match, Redirect } from "react-router";
import { default as load } from "../module/load";
import { ApplicationStore } from "../store/ApplicationStore";
import { UserStoreKey, UserStoreStructure } from "../store/UserStore";
function isNode() {
return typeof global === 'object' && typeof process === 'object'
&& Object.prototype.toString.call(process) === '[object process]';
}
interface NestedProps {
module: () => Promise<any>;
render: (props) => (module) => any;
/**
* This is injected by mobx-react Provider
*/
store?: ApplicationStore;
}
interface NestedState {
module: React.ReactType;
}
/**
* This class is for internal use by LazyRoute.
*/
@observer
class Nested extends React.Component<NestedProps, NestedState>{
state: NestedState = {
module: null
};
_isMounted: boolean;
componentWillMount() {
this._isMounted = true;
if (exists(module, this.props.module)) {
const {info, loadedModule} = fetch(module, this.props.module);
this.setState({ module: loadedModule });
} else {
console.log("async route load");
var task = load<React.ReactType>(module, this.props.module)(this.props.module()).then(({ info, module: loadedModule }) => {
add(module, this.props.module, { info, loadedModule });
if (!isNode()) {
if (this._isMounted) {
this.setState({ module: loadedModule });
}
}
});
addTask(task);
}
}
componentWillUnmount() {
this._isMounted = false;
}
render() {
let {
render,
module,
} = this.props;
return render(this.props)(this.state.module);
}
}
interface LazyRouteProps {
pattern: string;
module: () => Promise<any>;
/*
Defaults True - redirects to login when user is not logged in
When False - redirects to home page when user is logged in (only used on the login page and pages that should only be viewed by non logged in users)
*/
onlyAuthorizedUsers?: boolean;
exactly?: boolean;
render?: (props) => (module) => any;
}
interface LazyRouteStores {
stores: UserStoreStructure;
}
@observer
class LazyRoute extends React.Component<LazyRouteProps & LazyRouteStores, {}> {
static defaultProps: any = {
render: props => Component => Component && Component.default ? <Component.default {...props} /> : null,
onlyAuthorizedUsers: true,
};
render() {
const {children, onlyAuthorizedUsers, stores: {user}} = this.props;
return (
<Match
pattern={this.props.pattern}
exactly={this.props.exactly}
render={props => {
var nested = <Nested {...props} module={this.props.module} render={this.props.render} />;
return onlyAuthorizedUsers ?
(user.isLoggedIn ?
nested :
<Redirect to={{ pathname: '/login', state: { from: props.location } }} />) :
(!user.isLoggedIn ?
nested :
<Redirect to="/" />)
}
}
/>
);
}
}
export default inject<LazyRouteProps, LazyRouteStores>(UserStoreKey)(LazyRoute);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment