1 | import { createBrowserHistory } from 'history';
|
2 | import React from 'react';
|
3 | import { NavigationActions, getNavigation } from '@react-navigation/core';
|
4 | const queryString = require('query-string');
|
5 |
|
6 | const history = createBrowserHistory();
|
7 |
|
8 | const getPathAndParamsFromLocation = location => {
|
9 | const path = location.pathname.substr(1);
|
10 | const params = queryString.parse(location.search);
|
11 | return { path, params };
|
12 | };
|
13 |
|
14 | const matchPathAndParams = (a, b) => {
|
15 | if (a.path !== b.path) {
|
16 | return false;
|
17 | }
|
18 | if (queryString.stringify(a.params) !== queryString.stringify(b.params)) {
|
19 | return false;
|
20 | }
|
21 | return true;
|
22 | };
|
23 |
|
24 | let currentPathAndParams = getPathAndParamsFromLocation(history.location);
|
25 |
|
26 | export default function createBrowserApp(App) {
|
27 | const setHistoryListener = dispatch => {
|
28 | history.listen(location => {
|
29 | const pathAndParams = getPathAndParamsFromLocation(location);
|
30 | if (matchPathAndParams(pathAndParams, currentPathAndParams)) {
|
31 | return;
|
32 | }
|
33 | currentPathAndParams = pathAndParams;
|
34 | const action = App.router.getActionForPathAndParams(pathAndParams.path, pathAndParams.params);
|
35 | dispatch(action);
|
36 | });
|
37 | };
|
38 |
|
39 | const initAction = App.router.getActionForPathAndParams(currentPathAndParams.path, currentPathAndParams.params) || NavigationActions.init();
|
40 |
|
41 | class WebApp extends React.Component {
|
42 | state = { nav: App.router.getStateForAction(initAction) };
|
43 | _title = document.title;
|
44 | _actionEventSubscribers = new Set();
|
45 | componentDidMount() {
|
46 | setHistoryListener(this._dispatch);
|
47 | this._actionEventSubscribers.forEach(subscriber => subscriber({
|
48 | type: 'action',
|
49 | action: initAction,
|
50 | state: this.state.nav,
|
51 | lastState: null
|
52 | }));
|
53 | }
|
54 | componentDidUpdate() {
|
55 | const { state, getChildNavigation } = this._navigation;
|
56 | const childKey = state.routes[state.index].key;
|
57 | const activeNav = this._navigation.getChildNavigation(childKey);
|
58 | const opts = App.router.getScreenOptions(activeNav);
|
59 | this._title = opts.title || opts.headerTitle;
|
60 | document.title = this._title;
|
61 | }
|
62 | render() {
|
63 | this._navigation = getNavigation(App.router, this.state.nav, this._dispatch, this._actionEventSubscribers, () => this.props.screenProps, () => this._navigation);
|
64 | return <App navigation={this._navigation} />;
|
65 | }
|
66 | _dispatch = action => {
|
67 | const lastState = this.state.nav;
|
68 | const newState = App.router.getStateForAction(action, lastState);
|
69 | const dispatchEvents = () => this._actionEventSubscribers.forEach(subscriber => subscriber({
|
70 | type: 'action',
|
71 | action,
|
72 | state: newState,
|
73 | lastState
|
74 | }));
|
75 | if (newState && newState !== lastState) {
|
76 | this.setState({ nav: newState }, dispatchEvents);
|
77 | const pathAndParams = App.router.getPathAndParamsForState && App.router.getPathAndParamsForState(newState);
|
78 | if (pathAndParams && !matchPathAndParams(pathAndParams, currentPathAndParams)) {
|
79 | currentPathAndParams = pathAndParams;
|
80 | history.push(`/${pathAndParams.path}?${queryString.stringify(pathAndParams.params)}`);
|
81 | }
|
82 | } else {
|
83 | dispatchEvents();
|
84 | }
|
85 | };
|
86 | }
|
87 | return WebApp;
|
88 | } |
\ | No newline at end of file |