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:
parent
b0bf60bd7d
commit
dbe96d33f9
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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';
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 };
|
||||
}
|
||||
|
16
src/root.js
16
src/root.js
@ -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>
|
||||
);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
);
|
84
yarn.lock
84
yarn.lock
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user