Upgrade to React Router v4 (#667)

* Upgrade to React Router v4

* Fix pages not change when the URL was changed.

This issue is due to the Redux `connect` wrapper around `<App/>`.
`connect` diffs changes in regular props to know when to update the
component, but doesn't check context props like `location`.
See
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md.

* Update to new `history` methods.
This commit is contained in:
Caleb 2017-10-12 19:10:43 -06:00 committed by Shawn Erquhart
parent b0bf60bd7d
commit dbe96d33f9
11 changed files with 92 additions and 109 deletions

View File

@ -72,10 +72,10 @@
"babel-jest": "^21.2.0",
"babel-loader": "^7.0.0",
"babel-plugin-lodash": "^3.2.0",
"babel-plugin-transform-builtin-extend": "^1.1.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.23.0",
"babel-preset-stage-1": "^6.22.0",
"babel-plugin-transform-builtin-extend": "^1.1.0",
"babel-runtime": "^6.23.0",
"cross-env": "^5.0.2",
"css-loader": "^0.28.7",
@ -118,7 +118,7 @@
"fuzzy": "^0.1.1",
"gotrue-js": "^0.9.11",
"gray-matter": "^3.0.6",
"history": "^2.1.2",
"history": "^4.7.2",
"immutable": "^3.7.6",
"js-base64": "^2.1.9",
"js-yaml": "^3.10.0",
@ -139,8 +139,8 @@
"react-hot-loader": "^3.0.0-beta.7",
"react-immutable-proptypes": "^2.1.0",
"react-redux": "^4.4.0",
"react-router": "^2.5.1",
"react-router-redux": "^4.0.5",
"react-router-dom": "^4.2.2",
"react-router-redux": "^5.0.0-alpha.6",
"react-sidebar": "^2.2.1",
"react-simple-dnd": "^0.1.2",
"react-sortable": "^1.2.0",

View File

@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React from "react";
import ImmutablePropTypes from "react-immutable-proptypes";
import { IndexLink } from "react-router";
import { Link } from 'react-router-dom';
import { IconMenu, Menu, MenuItem } from "react-toolbox/lib/menu";
import Avatar from "react-toolbox/lib/avatar";
import AppBar from "react-toolbox/lib/app_bar";
@ -66,9 +66,9 @@ export default class AppHeader extends React.Component {
onLeftIconClick={toggleDrawer}
onRightIconClick={this.handleRightIconClick}
>
<IndexLink to="/" className={styles.homeLink}>
<Link to="/" className={styles.homeLink}>
<FontIcon value="home" className={styles.icon} />
</IndexLink>
</Link>
<IconMenu
theme={styles}
icon="add"

View File

@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import { DragSource, DropTarget, HTML5DragDrop } from 'react-simple-dnd';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { Link } from 'react-router';
import { Link } from 'react-router-dom';
import moment from 'moment';
import { capitalize } from 'lodash'
import { Card, CardTitle, CardText, CardActions } from 'react-toolbox/lib/card';

View File

@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { IndexLink } from "react-router";
import { Route, Switch, Link } from 'react-router-dom';
import FontIcon from 'react-toolbox/lib/font_icon';
import { Navigation } from 'react-toolbox/lib/navigation';
import { Notifs } from 'redux-notifications';
@ -21,6 +21,11 @@ import AppHeader from '../components/AppHeader/AppHeader';
import { Loader, Toast } from '../components/UI/index';
import { getCollectionUrl, getNewEntryUrl } from '../lib/urlHelper';
import { SIMPLE, EDITORIAL_WORKFLOW } from '../constants/publishModes';
import DashboardPage from './DashboardPage';
import CollectionPage from './CollectionPage';
import EntryPage from './EntryPage';
import SearchPage from './SearchPage';
import NotFoundPage from './NotFoundPage';
import styles from './App.css';
import sidebarStyles from './Sidebar.css';
@ -38,7 +43,6 @@ class App extends React.Component {
static propTypes = {
auth: ImmutablePropTypes.map,
children: PropTypes.node,
config: ImmutablePropTypes.map,
collections: ImmutablePropTypes.orderedMap,
createNewEntryInCollection: PropTypes.func.isRequired,
@ -104,7 +108,6 @@ class App extends React.Component {
const {
user,
config,
children,
collections,
toggleSidebar,
runCommand,
@ -140,7 +143,7 @@ class App extends React.Component {
<section>
<h1 className={sidebarStyles.heading}>Publishing</h1>
<div className={sidebarStyles.linkWrapper}>
<IndexLink to="/" className={sidebarStyles.viewEntriesLink}>Editorial Workflow</IndexLink>
<Link to="/" className={sidebarStyles.viewEntriesLink}>Editorial Workflow</Link>
</div>
</section>
}
@ -193,7 +196,14 @@ class App extends React.Component {
<div className={styles.entriesPanel}>
{ isFetching && <TopBarProgress /> }
<div>
{children}
<Switch>
<Route exact path='/' component={DashboardPage} />
<Route exact path="/collections/:name" component={CollectionPage} />
<Route path="/collections/:name/entries/new" render={(props) => (<EntryPage {...props} newRecord={true}/>)} />
<Route path="/collections/:name/entries/:slug" component={EntryPage} />
<Route path="/search/:searchTerm" component={SearchPage} />
<Route component={NotFoundPage} />
</Switch>
</div>
</div>
</div>

View File

@ -68,7 +68,7 @@ class CollectionPage extends React.Component {
function mapStateToProps(state, ownProps) {
const { collections, config } = state;
const { name, slug } = ownProps.params;
const { name } = ownProps.match.params;
const publicFolder = config.get('public_folder');
const collection = name ? collections.get(name) : collections.first();
const page = state.entries.getIn(['pages', collection.get('name'), 'page']);
@ -76,7 +76,7 @@ function mapStateToProps(state, ownProps) {
const entries = selectEntries(state, collection.get('name'));
const isFetching = state.entries.getIn(['pages', collection.get('name'), 'isFetching'], false);
return { slug, publicFolder, collection, collections, page, entries, isFetching };
return { publicFolder, collection, collections, page, entries, isFetching };
}
export default connect(mapStateToProps)(CollectionPage);

View File

@ -56,11 +56,10 @@ class EntryPage extends React.Component {
loadEntry(collection, slug);
}
this.unlisten = history.listenBefore((location) => {
this.unblock = history.block((location) => {
if (this.props.entryDraft.get('hasChanged')) {
return "Are you sure you want to leave this page?";
}
return true;
});
}
@ -84,7 +83,7 @@ class EntryPage extends React.Component {
componentWillUnmount() {
this.props.discardDraft();
this.unlisten();
this.unblock();
}
createDraft = (entry) => {
@ -161,9 +160,9 @@ class EntryPage extends React.Component {
function mapStateToProps(state, ownProps) {
const { collections, entryDraft } = state;
const slug = ownProps.params.slug;
const collection = collections.get(ownProps.params.name);
const newEntry = ownProps.route && ownProps.route.newRecord === true;
const slug = ownProps.match.params.slug;
const collection = collections.get(ownProps.match.params.name);
const newEntry = ownProps.newRecord === true;
const fields = selectFields(collection, slug);
const entry = newEntry ? null : selectEntry(state, collection.get('name'), slug);
const boundGetAsset = getAsset.bind(null, state);

View File

@ -67,7 +67,7 @@ function mapStateToProps(state, ownProps) {
const entries = selectSearchedEntries(state);
const collections = state.collections.toIndexedSeq();
const publicFolder = state.config.get('public_folder');
const searchTerm = ownProps.params && ownProps.params.searchTerm;
const { searchTerm } = ownProps.match.params;
return { isFetching, page, collections, entries, publicFolder, searchTerm };
}

View File

@ -1,23 +1,21 @@
import React from 'react';
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import routes from './routing/routes';
import history, { syncHistory } from './routing/history';
import { Route } from 'react-router-dom';
import { ConnectedRouter } from 'react-router-redux';
import history from './routing/history';
import configureStore from './redux/configureStore';
import { setStore } from './valueObjects/AssetProxy';
import App from './containers/App';
const store = configureStore();
// Create an enhanced history that syncs navigation events with the store
syncHistory(store);
setStore(store);
const Root = () => (
<Provider store={store}>
<Router history={history}>
{routes}
</Router>
<ConnectedRouter history={history}>
<Route component={App}/>
</ConnectedRouter>
</Provider>
);

View File

@ -1,14 +1,5 @@
import { createHashHistory } from 'history';
import { useRouterHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import createHistory from 'history/createHashHistory';
let history = useRouterHistory(createHashHistory)({
queryKey: false
});
let history = createHistory();
const syncHistory = (store) => {
history = syncHistoryWithStore(history, store);
};
export { syncHistory };
export default history;

View File

@ -1,35 +0,0 @@
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from '../containers/App';
import DashboardPage from '../containers/DashboardPage';
import CollectionPage from '../containers/CollectionPage';
import EntryPage from '../containers/EntryPage';
import SearchPage from '../containers/SearchPage';
import NotFoundPage from '../containers/NotFoundPage';
export default (
<Route path="/" component={App}>
<IndexRoute component={DashboardPage} />
<Route
path="/collections/:name"
component={CollectionPage}
/>
<Route
path="/collections/:name/entries/new"
component={EntryPage}
newRecord
/>
<Route
path="/collections/:name/entries/:slug"
component={EntryPage}
/>
<Route
path="/search/:searchTerm"
component={SearchPage}
/>
<Route
path="*"
component={NotFoundPage}
/>
</Route>
);

View File

@ -2192,7 +2192,7 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
deep-equal@^1.0.0, deep-equal@^1.0.1, deep-equal@~1.0.1:
deep-equal@^1.0.1, deep-equal@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
@ -3741,14 +3741,15 @@ highlight-es@^1.0.0:
is-es2016-keyword "^1.0.0"
js-tokens "^3.0.0"
history@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/history/-/history-2.1.2.tgz#4aa2de897a0e4867e4539843be6ecdb2986bfdec"
history@^4.5.1, history@^4.7.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b"
dependencies:
deep-equal "^1.0.0"
invariant "^2.0.0"
query-string "^3.0.0"
warning "^2.0.0"
invariant "^2.2.1"
loose-envify "^1.2.0"
resolve-pathname "^2.2.0"
value-equal "^0.4.0"
warning "^3.0.0"
hmac-drbg@^1.0.0:
version "1.0.1"
@ -3770,7 +3771,7 @@ hoist-non-react-statics@1.x.x, hoist-non-react-statics@^1.0.3, hoist-non-react-s
version "1.2.0"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
hoist-non-react-statics@^2.1.0, hoist-non-react-statics@^2.2.1:
hoist-non-react-statics@^2.1.0, hoist-non-react-statics@^2.2.1, hoist-non-react-statics@^2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
@ -6096,6 +6097,12 @@ path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
path-to-regexp@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
dependencies:
isarray "0.0.1"
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@ -6882,12 +6889,6 @@ qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
query-string@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-3.0.3.tgz#ae2e14b4d05071d4e9b9eb4873c35b0dcd42e638"
dependencies:
strict-uri-encode "^1.0.0"
query-string@^4.1.0:
version "4.3.4"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
@ -7126,18 +7127,35 @@ react-redux@^5.0.1:
loose-envify "^1.1.0"
prop-types "^15.5.10"
react-router-redux@^4.0.5:
version "4.0.8"
resolved "https://registry.yarnpkg.com/react-router-redux/-/react-router-redux-4.0.8.tgz#227403596b5151e182377dab835b5d45f0f8054e"
react-router@^2.5.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-2.8.1.tgz#73e9491f6ceb316d0f779829081863e378ee4ed7"
react-router-dom@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.2.2.tgz#c8a81df3adc58bba8a76782e946cbd4eae649b8d"
dependencies:
history "^2.1.2"
hoist-non-react-statics "^1.2.0"
invariant "^2.2.1"
loose-envify "^1.2.0"
history "^4.7.2"
invariant "^2.2.2"
loose-envify "^1.3.1"
prop-types "^15.5.4"
react-router "^4.2.0"
warning "^3.0.0"
react-router-redux@^5.0.0-alpha.6:
version "5.0.0-alpha.6"
resolved "https://registry.yarnpkg.com/react-router-redux/-/react-router-redux-5.0.0-alpha.6.tgz#7418663c2ecd3c51be856fcf28f3d1deecc1a576"
dependencies:
history "^4.5.1"
prop-types "^15.5.4"
react-router "^4.1.1"
react-router@^4.1.1, react-router@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.2.0.tgz#61f7b3e3770daeb24062dae3eedef1b054155986"
dependencies:
history "^4.7.2"
hoist-non-react-statics "^2.3.0"
invariant "^2.2.2"
loose-envify "^1.3.1"
path-to-regexp "^1.7.0"
prop-types "^15.5.4"
warning "^3.0.0"
react-sidebar@^2.2.1:
@ -7670,6 +7688,10 @@ resolve-from@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
resolve-pathname@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879"
resolve@1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
@ -9063,6 +9085,10 @@ validate-npm-package-license@^3.0.1:
spdx-correct "~1.0.0"
spdx-expression-parse "~1.0.0"
value-equal@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7"
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@ -9111,12 +9137,6 @@ walker@~1.0.5:
dependencies:
makeerror "1.0.x"
warning@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/warning/-/warning-2.1.0.tgz#21220d9c63afc77a8c92111e011af705ce0c6901"
dependencies:
loose-envify "^1.0.0"
warning@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"