Preloading ready
This commit is contained in:
Generated
+8
@@ -11570,6 +11570,14 @@
|
||||
"integrity": "sha512-FlsPxavEyMuR6TjVbSSywovXSEyOg6ZDj5+Z8nbsRl9EkOzAhEIcS+GLoQDC5fz/t9suhUXWmUrOBrgeUvrMxw==",
|
||||
"dev": true
|
||||
},
|
||||
"react-loadable": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-loadable/-/react-loadable-5.4.0.tgz",
|
||||
"integrity": "sha512-HAFWL3aLB9dQA6OfGr7ACDNn/mv8jPUmBvXqrhJZfZgRhZysyNW8RupvGUbeGkTO+9frH1LTdJmKWphZENhlJg==",
|
||||
"requires": {
|
||||
"prop-types": "^15.5.0"
|
||||
}
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "5.0.7",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
"connected-react-router": "^4.3.0",
|
||||
"react": "^16.4.1",
|
||||
"react-dom": "^16.4.1",
|
||||
"react-loadable": "^5.4.0",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"redux": "^4.0.0",
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { BrowserRouter, Switch, Route, Link } from "react-router-dom";
|
||||
|
||||
import {
|
||||
AsyncAlpha,
|
||||
AsyncBravo,
|
||||
AsyncCharlie,
|
||||
AsyncZulu,
|
||||
AsyncHelp
|
||||
} from "./splittingApp";
|
||||
|
||||
const Home = () => <h1>Home Sweet Home</h1>;
|
||||
const Error404 = () => <h1>404 Error!</h1>;
|
||||
|
||||
class App extends Component<{}> {
|
||||
render() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<div>
|
||||
<header>
|
||||
<nav>
|
||||
<Link to="/">Home</Link>
|
||||
<Link to="/alpha">
|
||||
<span
|
||||
onMouseOver={() =>
|
||||
AsyncAlpha.preload()
|
||||
}
|
||||
>
|
||||
Alpha...
|
||||
</span>
|
||||
</Link>
|
||||
<Link to="/bravo">Bravo...</Link>
|
||||
<Link to="/charlie">Charlie...</Link>
|
||||
<Link to="/wrong">...Wrong...</Link>
|
||||
<Link to="/zulu">Zulu</Link>
|
||||
<Link to="/help">Help</Link>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/help" component={AsyncHelp} />
|
||||
<Route path="/alpha" component={AsyncAlpha} />
|
||||
<Route path="/bravo" component={AsyncBravo} />
|
||||
<Route path="/charlie" component={AsyncCharlie} />
|
||||
<Route path="/zulu" component={AsyncZulu} />
|
||||
<Route component={Error404} />
|
||||
</Switch>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
import App from "./App.routing.auth";
|
||||
import App from "./App.splitting";
|
||||
import registerServiceWorker from "./registerServiceWorker";
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById("root"));
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
|
||||
const Alpha = () => <h1>Alpha</h1>;
|
||||
|
||||
export default Alpha;
|
||||
@@ -0,0 +1,10 @@
|
||||
/* @flow */
|
||||
|
||||
import Loadable from "react-loadable";
|
||||
|
||||
import { LoadingStatus } from "./loadingStatus.component";
|
||||
|
||||
export const AsyncAlpha = Loadable({
|
||||
loader: () => import("./alpha.component"),
|
||||
loading: LoadingStatus
|
||||
});
|
||||
@@ -1,33 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import { Route, Redirect } from "react-router-dom";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
export class Auth extends React.Component<{
|
||||
loginRoute: string,
|
||||
token: string,
|
||||
location: object
|
||||
}> {
|
||||
static propTypes = {
|
||||
loginRoute: PropTypes.string.isRequired,
|
||||
token: PropTypes.string.isRequired,
|
||||
location: PropTypes.object
|
||||
};
|
||||
|
||||
render() {
|
||||
const myProps = { ...this.props };
|
||||
if (!myProps.token) {
|
||||
delete myProps.component;
|
||||
myProps.render = () => (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: this.props.loginRoute,
|
||||
state: { from: this.props.location }
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <Route {...myProps} />;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { Auth } from "./authRoute.component";
|
||||
export const AuthRoute = connect(state => ({
|
||||
token: state.token,
|
||||
loginRoute: "/login"
|
||||
}))(Auth);
|
||||
@@ -0,0 +1,7 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
|
||||
const Bravo = () => <h1>Bravo</h1>;
|
||||
|
||||
export default Bravo;
|
||||
@@ -0,0 +1,10 @@
|
||||
/* @flow */
|
||||
|
||||
import Loadable from "react-loadable";
|
||||
|
||||
import { LoadingStatus } from "./loadingStatus.component";
|
||||
|
||||
export const AsyncBravo = Loadable({
|
||||
loader: () => import("./bravo.component"),
|
||||
loading: LoadingStatus
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
|
||||
const Charlie = () => <h1>Charlie</h1>;
|
||||
|
||||
export default Charlie;
|
||||
@@ -0,0 +1,10 @@
|
||||
/* @flow */
|
||||
|
||||
import Loadable from "react-loadable";
|
||||
|
||||
import { LoadingStatus } from "./loadingStatus.component";
|
||||
|
||||
export const AsyncCharlie = Loadable({
|
||||
loader: () => import("./charlie.component"),
|
||||
loading: LoadingStatus
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
|
||||
const Help = () => <h1>Help! SOS!</h1>;
|
||||
|
||||
export default Help;
|
||||
@@ -0,0 +1,10 @@
|
||||
/* @flow */
|
||||
|
||||
import Loadable from "react-loadable";
|
||||
|
||||
import { LoadingStatus } from "./loadingStatus.component";
|
||||
|
||||
export const AsyncHelp = Loadable({
|
||||
loader: () => import("./help.component"),
|
||||
loading: LoadingStatus
|
||||
});
|
||||
@@ -1,7 +1,9 @@
|
||||
/* @flow */
|
||||
|
||||
import { ConnectedLogin } from "./login.connected.js";
|
||||
import { ConnectedProtectedRoutes } from "./protectedRoutes.connected.js";
|
||||
import { AuthRoute } from "./authRoute.connected.js";
|
||||
import { AsyncAlpha } from "./alpha.loadable";
|
||||
import { AsyncBravo } from "./bravo.loadable";
|
||||
import { AsyncCharlie } from "./charlie.loadable";
|
||||
import { AsyncZulu } from "./zulu.loadable";
|
||||
import { AsyncHelp } from "./help.loadable";
|
||||
|
||||
export { ConnectedLogin, ConnectedProtectedRoutes, AuthRoute };
|
||||
export { AsyncAlpha, AsyncBravo, AsyncCharlie, AsyncZulu, AsyncHelp };
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
export class LoadingStatus extends React.Component<{
|
||||
isLoading: boolean,
|
||||
error: boolean
|
||||
}> {
|
||||
static propTypes = {
|
||||
isLoading: PropTypes.bool,
|
||||
error: PropTypes.bool
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.props.isLoading) {
|
||||
return <div>Loading...</div>;
|
||||
} else if (this.props.error) {
|
||||
return <div>ERROR: the component could not be loaded.</div>;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import { loginService } from "./serviceApi";
|
||||
|
||||
export const LOGIN_REQUEST = "login:request";
|
||||
export const LOGIN_SUCCESS = "login:success";
|
||||
export const LOGIN_FAILURE = "login:failure";
|
||||
|
||||
export const loginRequest = () => ({
|
||||
type: LOGIN_REQUEST
|
||||
});
|
||||
|
||||
export const loginSuccess = (token: string) => ({
|
||||
type: LOGIN_SUCCESS,
|
||||
token
|
||||
});
|
||||
|
||||
export const loginFailure = () => ({
|
||||
type: LOGIN_FAILURE
|
||||
});
|
||||
|
||||
// Complex actions:
|
||||
|
||||
export const attemptLogin = (
|
||||
user: string,
|
||||
password: string
|
||||
) => async dispatch => {
|
||||
try {
|
||||
dispatch(loginRequest());
|
||||
// the next line delays execution for 5 seconds:
|
||||
// await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
const result = await loginService(user, password);
|
||||
dispatch(loginSuccess(result.data));
|
||||
} catch (e) {
|
||||
dispatch(loginFailure());
|
||||
}
|
||||
};
|
||||
@@ -1,68 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { Redirect } from "react-router-dom";
|
||||
|
||||
export class Login extends React.PureComponent<{
|
||||
onLogin: func,
|
||||
logging: boolean,
|
||||
token: string,
|
||||
location: object
|
||||
}> {
|
||||
static propTypes = {
|
||||
onLogin: PropTypes.func.isRequired,
|
||||
logging: PropTypes.bool.isRequired,
|
||||
token: PropTypes.string.isRequired,
|
||||
location: PropTypes.object
|
||||
};
|
||||
|
||||
state = {
|
||||
userName: "",
|
||||
password: ""
|
||||
};
|
||||
|
||||
onUserNameBlur = e => this.setState({ userName: e.target.value });
|
||||
|
||||
onPasswordBlur = e => this.setState({ password: e.target.value });
|
||||
|
||||
onLoginClick = () =>
|
||||
this.props.onLogin(this.state.userName, this.state.password);
|
||||
|
||||
render() {
|
||||
if (
|
||||
this.state.userName &&
|
||||
this.state.password &&
|
||||
this.props.token
|
||||
) {
|
||||
return (
|
||||
<Redirect to={this.props.location.state.from.pathname} />
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<h1>Login Form</h1>
|
||||
<div>
|
||||
User:<input
|
||||
type="text"
|
||||
onBlur={this.onUserNameBlur}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
Password:
|
||||
<input
|
||||
type="password"
|
||||
onBlur={this.onPasswordBlur}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
onClick={this.onLoginClick}
|
||||
disabled={this.props.logging}
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { Login } from "./login.component";
|
||||
import { attemptLogin } from "./login.actions";
|
||||
|
||||
export const ConnectedLogin = connect(
|
||||
state => ({
|
||||
logging: state.logging,
|
||||
token: state.token
|
||||
}),
|
||||
dispatch => ({
|
||||
onLogin: (user: string, password: string) =>
|
||||
dispatch(attemptLogin(user, password))
|
||||
})
|
||||
)(Login);
|
||||
@@ -1,41 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import {
|
||||
LOGIN_REQUEST,
|
||||
LOGIN_SUCCESS,
|
||||
LOGIN_FAILURE
|
||||
} from "./login.actions";
|
||||
|
||||
export const reducer = (
|
||||
state: object = {
|
||||
// initial state
|
||||
logging: false,
|
||||
token: ""
|
||||
},
|
||||
action
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case LOGIN_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
logging: true,
|
||||
token: ""
|
||||
};
|
||||
|
||||
case LOGIN_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
logging: false,
|
||||
token: action.token
|
||||
};
|
||||
|
||||
case LOGIN_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
logging: false
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
import { Redirect, Switch } from "react-router-dom";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
export class ProtectedRoutes extends React.Component<{
|
||||
token: string,
|
||||
children: any,
|
||||
location: object
|
||||
}> {
|
||||
static propTypes = {
|
||||
token: PropTypes.string.isRequired,
|
||||
children: PropTypes.any,
|
||||
location: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
render() {
|
||||
return this.props.token ? (
|
||||
<Switch>{this.props.children}</Switch>
|
||||
) : (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: "/login",
|
||||
state: { from: this.props.location }
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { ProtectedRoutes } from "./protectedRoutes.component";
|
||||
|
||||
export const ConnectedProtectedRoutes = connect(state => ({
|
||||
token: state.token
|
||||
}))(ProtectedRoutes);
|
||||
@@ -1,9 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import axios from "axios";
|
||||
|
||||
export const loginService = (user, password) =>
|
||||
axios.post(
|
||||
`http://localhost:8443/gettoken`,
|
||||
`user=${user}&password=${password}`
|
||||
);
|
||||
@@ -1,8 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import { createStore, applyMiddleware } from "redux";
|
||||
import thunk from "redux-thunk";
|
||||
|
||||
import { reducer } from "./login.reducer";
|
||||
|
||||
export const store = createStore(reducer, applyMiddleware(thunk));
|
||||
@@ -0,0 +1,7 @@
|
||||
/* @flow */
|
||||
|
||||
import React from "react";
|
||||
|
||||
const Zulu = () => <h1>Zulu</h1>;
|
||||
|
||||
export default Zulu;
|
||||
@@ -0,0 +1,10 @@
|
||||
/* @flow */
|
||||
|
||||
import Loadable from "react-loadable";
|
||||
|
||||
import { LoadingStatus } from "./loadingStatus.component";
|
||||
|
||||
export const AsyncZulu = Loadable({
|
||||
loader: () => import("./zulu.component"),
|
||||
loading: LoadingStatus
|
||||
});
|
||||
Reference in New Issue
Block a user