UNPKG

3.23 kBJavaScriptView Raw
1import { createBrowserHistory } from 'history';
2import React from 'react';
3import { NavigationActions, getNavigation } from '@react-navigation/core';
4const queryString = require('query-string');
5
6const history = createBrowserHistory();
7
8const getPathAndParamsFromLocation = location => {
9 const path = location.pathname.substr(1);
10 const params = queryString.parse(location.search);
11 return { path, params };
12};
13
14const 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
24let currentPathAndParams = getPathAndParamsFromLocation(history.location);
25
26export 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