finish history routing

This commit is contained in:
Jeff Colombo 2019-03-21 00:02:41 -04:00
parent c2f48865b7
commit 7cc5e9c77f
8 changed files with 112 additions and 54 deletions

File diff suppressed because one or more lines are too long

14
dist/main-bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@ -79,7 +79,9 @@
},
"dependencies": {
"classnames": "^2.2.6",
"history": "^4.9.0",
"nes.css": "^2.0.0",
"path-to-regexp": "^3.0.0",
"pokemongo-json-pokedex": "^3.4.6",
"prop-types": "^15.6.2",
"react": "^16.7.0",

View File

@ -44,8 +44,13 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
public async componentWillMount() {
const {
dispatch
dispatch,
match,
} = this.props;
const {
id,
form,
} = match.params;
await Promise.all([
dispatch(ActionsPokemonApp.fetchConfig()),
@ -53,6 +58,12 @@ class PokemonApp extends React.Component<IConnectedPokemonAppProps, IState> {
dispatch(ActionsPokemonSelectList.fetchPokemonList())
]);
dispatch(ActionsPokemonSelectList.setIsLoading(false));
const pokemonId = convertIdParamToPokemonId(id);
const pokemonForm = convertFormParamToPokemonForm(form);
if (pokemonId !== null && pokemonForm !== null) {
this.handleActivatePokemon(pokemonId, pokemonForm);
}
}
public render() {

View File

@ -1,11 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
import { Redirect, Route, Router, Switch } from 'react-router-dom';
import * as Redux from 'redux';
import thunk from 'redux-thunk';
import { routePokemonApp } from 'app/router';
import { HistoryRouter } from 'app/models/HistoryRouter';
import { IPokemonAppExtraArguments, IRouterProps } from 'app/types';
import { PokemonService } from 'api/PokemonService';
@ -36,18 +36,13 @@ const store = Redux.createStore(
)
);
const renderRoutePokemonApp = (props : IRouterProps) => {
routePokemonApp(props, store.dispatch);
return (
<ConnectedPokemonApp />
);
};
const historyRouter = new HistoryRouter(store.dispatch);
ReactDOM.render(
<Provider store={ store }>
<Router>
<Router history={ historyRouter.getHistory() }>
<Switch>
<Route path="/explorer/:id/:form" render={ renderRoutePokemonApp } />
<Route path={ historyRouter.getRoutePath('PokemonExplorer') } component={ ConnectedPokemonApp } />
<Redirect from="/" to="/explorer/1/0" />
</Switch>

View File

@ -0,0 +1,79 @@
import { createBrowserHistory } from 'history';
import pathToRegexp from 'path-to-regexp';
import { IPokemonAppDispatch } from 'app/types';
import * as ActionsPokemonApp from 'app/actions';
import * as ActionsPokemonExplorer from 'app/components/PokemonExplorer/actions';
import { convertFormParamToPokemonForm, convertIdParamToPokemonId, convertLeagueParamToLeague } from 'app/utils/navigation';
type RouteType = 'PokemonExplorer';
type RoutePath = {
[key in RouteType] : string;
};
type PathRegexp = {
[key in RouteType] : ReturnType<typeof pathToRegexp>;
};
export class HistoryRouter {
private static readonly routePaths : RoutePath = {
PokemonExplorer: '/explorer/:id/:form',
};
private readonly pathRegexps : PathRegexp;
private readonly browserHistory : ReturnType<typeof createBrowserHistory>;
private readonly unregisterCallback : ReturnType<ReturnType<typeof createBrowserHistory>['listen']>;
constructor(
readonly dispatch : IPokemonAppDispatch['dispatch']
) {
this.pathRegexps = {
PokemonExplorer: pathToRegexp(HistoryRouter.routePaths.PokemonExplorer),
};
this.browserHistory = createBrowserHistory();
this.unregisterCallback = this.browserHistory.listen((location, action) => {
if (action === 'POP') {
const explorerResult = this.pathRegexps.PokemonExplorer.exec(location.pathname);
if (explorerResult !== null) {
this.routePokemonApp(explorerResult);
}
}
});
}
public unregister() {
this.unregisterCallback();
}
public getHistory() {
return this.browserHistory;
}
public getRoutePath(key : keyof RoutePath) {
return HistoryRouter.routePaths[key];
}
private async routePokemonApp(routeResult : Array<string>) {
const pokemonId = convertIdParamToPokemonId(routeResult[1]);
const pokemonForm = convertFormParamToPokemonForm(routeResult[2]);
if (pokemonId !== null && pokemonForm !== null) {
this.dispatch(ActionsPokemonExplorer.setIsLoading(true));
try {
const leaguePokemon = await this.dispatch(ActionsPokemonApp.fetchPokemonLeagueStats(pokemonId, pokemonForm));
this.dispatch(ActionsPokemonExplorer.reset(leaguePokemon));
} catch (error) {
// tslint:disable-next-line:no-console
console.error(error);
this.dispatch(ActionsPokemonExplorer.setLeaguePokemon(null));
}
this.dispatch(ActionsPokemonExplorer.setIsLoading(false));
}
// TODO: this doesn't do anything, league isn't even in the route
const activeLeague = convertLeagueParamToLeague(routeResult[3]);
if (activeLeague !== null) {
this.dispatch(ActionsPokemonExplorer.setActiveLeague(activeLeague));
}
}
}

View File

@ -1,34 +0,0 @@
import { IPokemonAppDispatch, IRouterProps } from 'app/types';
import * as ActionsPokemonApp from 'app/actions';
import * as ActionsPokemonExplorer from 'app/components/PokemonExplorer/actions';
import { convertFormParamToPokemonForm, convertIdParamToPokemonId, convertLeagueParamToLeague } from 'app/utils/navigation';
export const routePokemonApp = async (props : IRouterProps, dispatch : IPokemonAppDispatch['dispatch']) => {
const {
id,
form,
league,
} = props.match.params;
const pokemonId = convertIdParamToPokemonId(id);
const pokemonForm = convertFormParamToPokemonForm(form);
if (pokemonId !== null && pokemonForm !== null) {
dispatch(ActionsPokemonExplorer.setIsLoading(true));
try {
const leaguePokemon = await dispatch(ActionsPokemonApp.fetchPokemonLeagueStats(pokemonId, pokemonForm));
dispatch(ActionsPokemonExplorer.reset(leaguePokemon));
} catch (error) {
// tslint:disable-next-line:no-console
console.error(error);
dispatch(ActionsPokemonExplorer.setLeaguePokemon(null));
}
dispatch(ActionsPokemonExplorer.setIsLoading(false));
}
const activeLeague = convertLeagueParamToLeague(league);
if (activeLeague !== null) {
dispatch(ActionsPokemonExplorer.setActiveLeague(activeLeague));
}
};

View File

@ -3434,7 +3434,7 @@ he@1.1.1:
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
history@^4.7.2:
history@^4.7.2, history@^4.9.0:
version "4.9.0"
resolved "https://registry.yarnpkg.com/history/-/history-4.9.0.tgz#84587c2068039ead8af769e9d6a6860a14fa1bca"
integrity sha512-H2DkjCjXf0Op9OAr6nJ56fcRkTSNrUiv41vNJ6IswJjif6wlpZK0BTfFbi7qK9dXLSYZxkq5lBsj3vUjlYBYZA==
@ -5289,6 +5289,11 @@ path-to-regexp@^1.7.0:
dependencies:
isarray "0.0.1"
path-to-regexp@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-3.0.0.tgz#c981a218f3df543fa28696be2f88e0c58d2e012a"
integrity sha512-ZOtfhPttCrqp2M1PBBH4X13XlvnfhIwD7yCLx+GoGoXRPQyxGOTdQMpIzPSPKXAJT/JQrdfFrgdJOyAzvgpQ9A==
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"