Skip to content

Commit 134b5f9

Browse files
TobiahRexcoryhouse
authored andcommitted
Implement React Router@4.0.0 (#393)
* removed react-router form package.json & installed react-router-dom. * completed index.src refactor. * re-implemented App.js * added notes to import changes & App.js * modified middleware array @ store/configureStore.js * updated yarn.lock file with fresh `yarn` command. * updated master branch. * upgraded react-hot-reloader to @3.0.0-beta.6 * removed extra "document.getElementById(app) from Root.js * moved react-router-redux to regular "dependencies" from "dev-dependencies" * cleaned Root.propTypes. * cleaned Root.js & App.js per @oshalygin feedback. * replaced .gitignore comment. * removed react-router form package.json & installed react-router-dom. * completed index.src refactor. * re-implemented App.js * added notes to import changes & App.js * Update FAQ.md fixed header on FAQ page * Update README.md fixed a few headers improperly declared * modified middleware array @ store/configureStore.js * Add react hot loader 3 (#392) - This commit wires up react-hot-loader 3 to be used in the application. There are numerous benefits to the latest release, all of which can be seen at https://github.com/gaearon/react-hot-loader - Note that the specific implementation around wrapping in a Root component is part of how react-hot-loader 3 needs to be configured. - Note that the package is brought in as a dependency, not a dev dependency because of how it is switched at runtime or not. - More information on the migration can be viewed at: https://github.com/gaearon/react-hot-loader/tree/master/docs\#migration-to-30 Related: #216 * Updated react-hot-loader to correct package version. (#401) * Add item to check if issues * updated yarn.lock file with fresh `yarn` command. * Fix formatting (#403) * updated master branch. * upgraded react-hot-reloader to @3.0.0-beta.6 * removed extra "document.getElementById(app) from Root.js * moved react-router-redux to regular "dependencies" from "dev-dependencies" * cleaned Root.js & App.js per @oshalygin feedback. * replaced .gitignore comment. * clean index.js * Add CONTRIBUTE.md (#431) * Add * Updated yarn lock using upgrade * Rename * Update * Upgrade to webpack 3 * Update yarn lock * Update snapshot * Set prod env when analyzing bundle * Add jest-cli as dependency * Revert PR #450 (#451) Removed change that removed additional dashes in npm test scripts in favor of adding jest-cli as a devDep. This commit instead focusses on issue 2 from #449 where setupPrompts.js had a bug that caused start script to fail. * Issue #449 fix (#450) * Issue #449 fix Issue 1: Removed extra dashes located in the package.json test scripts that cause start script to fail. Issue 2: Removed escape characters found in setupPrompts.js which cause linting to fail, thus breaking start script. * Jest fix Re-added previously removed dashes from test scripts in package.json that caused start script to fail. Instead, @coryhouse added in jest-cli as a dev-dep which resolves the issue. * Enhance babel env config to transpile for IE9+ (#452) * Fix for jest handling of static assets when running tests. See: (#457) jestjs/jest#2663 (comment) * Added tips for npm run lint and build errors (#151) (#460) * pushing changes from upstream fetch. * updated from rebase. * modified package versions in package.json & created new build. * update package.json * fixed conflicts with upstream master. * cleaned up PropTypes validations - react-router-redux throwing PropTypes error. * comment spell check & de-console on Root.js
1 parent 8d68161 commit 134b5f9

17 files changed

+768
-880
lines changed

.watchmanconfig

Whitespace-only changes.

package.json

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@
3535
"react": "15.5.4",
3636
"react-dom": "15.5.4",
3737
"react-redux": "5.0.5",
38-
"react-router": "3.0.5",
39-
"react-router-redux": "4.0.8",
38+
"react-router": "4.2.0",
39+
"react-router-dom": "4.0.0",
40+
"react-router-redux": "5.0.0-alpha.6",
4041
"redux": "3.6.0",
4142
"redux-thunk": "2.1.0"
4243
},
@@ -66,6 +67,7 @@
6667
"eslint-watch": "3.1.2",
6768
"extract-text-webpack-plugin": "3.0.0-rc.2",
6869
"file-loader": "0.11.2",
70+
"history": "4.6.0",
6971
"html-webpack-plugin": "2.29.0",
7072
"identity-obj-proxy": "3.0.0",
7173
"jest": "20.0.4",
@@ -112,10 +114,10 @@
112114
"url": "https://github.com/coryhouse/react-slingshot"
113115
},
114116
"jest": {
115-
"moduleNameMapper": {
116-
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/tools/assetsTransformer.js",
117-
"\\.(css|less)$": "<rootDir>/tools/assetsTransformer.js"
118-
}
117+
"moduleNameMapper": {
118+
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/tools/assetsTransformer.js",
119+
"\\.(css|less)$": "<rootDir>/tools/assetsTransformer.js"
120+
}
119121
},
120122
"babel": {
121123
"presets": [

src/components/AboutPage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import {Link} from 'react-router';
2+
import { Link } from 'react-router-dom';
33
import '../styles/about-page.css';
44

55
// Since this component is simple and static, there's no parent container for it.

src/components/AboutPage.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import {shallow} from 'enzyme';
2+
import { shallow } from 'enzyme';
33
import AboutPage from './AboutPage';
44

55
describe('<AboutPage />', () => {

src/components/App.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
1+
/* eslint-disable import/no-named-as-default */
12
import React from 'react';
23
import PropTypes from 'prop-types';
3-
import { Link, IndexLink } from 'react-router';
4+
import { Route } from 'react-router';
5+
import { Switch, NavLink } from 'react-router-dom';
6+
import HomePage from './HomePage';
7+
import FuelSavingsPage from '../containers/FuelSavingsPage';
8+
import AboutPage from './AboutPage';
9+
import NotFoundPage from './NotFoundPage';
410

511
// This is a class-based component because the current
612
// version of hot reloading won't hot reload a stateless
713
// component at the top-level.
14+
815
class App extends React.Component {
916
render() {
17+
const activeStyle = { color: 'blue' };
1018
return (
1119
<div>
12-
<IndexLink to="/">Home</IndexLink>
13-
{' | '}
14-
<Link to="/fuel-savings">Demo App</Link>
15-
{' | '}
16-
<Link to="/about">About</Link>
17-
<br/>
18-
{this.props.children}
20+
<div>
21+
<NavLink exact to="/" activeStyle={activeStyle}>Home</NavLink>
22+
{' | '}
23+
<NavLink to="/fuel-savings" activeStyle={activeStyle}>Demo App</NavLink>
24+
{' | '}
25+
<NavLink to="/about" activeStyle={activeStyle}>About</NavLink>
26+
</div>
27+
<Switch>
28+
<Route exact path="/" component={HomePage} />
29+
<Route path="/fuel-savings" component={FuelSavingsPage} />
30+
<Route path="/about" component={AboutPage} />
31+
<Route component={NotFoundPage} />
32+
</Switch>
1933
</div>
2034
);
2135
}

src/components/FuelSavingsForm.js

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,48 +32,48 @@ class FuelSavingsForm extends React.Component {
3232
<h2>Fuel Savings Analysis</h2>
3333
<table>
3434
<tbody>
35-
<tr>
36-
<td><label htmlFor="newMpg">New Vehicle MPG</label></td>
37-
<td><FuelSavingsTextInput onChange={this.fuelSavingsKeypress} name="newMpg" value={fuelSavings.newMpg}/>
38-
</td>
39-
</tr>
40-
<tr>
41-
<td><label htmlFor="tradeMpg">Trade-in MPG</label></td>
42-
<td><FuelSavingsTextInput onChange={this.fuelSavingsKeypress} name="tradeMpg" value={fuelSavings.tradeMpg}/>
43-
</td>
44-
</tr>
45-
<tr>
46-
<td><label htmlFor="newPpg">New Vehicle price per gallon</label></td>
47-
<td><FuelSavingsTextInput onChange={this.fuelSavingsKeypress} name="newPpg" value={fuelSavings.newPpg}/>
48-
</td>
49-
</tr>
50-
<tr>
51-
<td><label htmlFor="tradePpg">Trade-in price per gallon</label></td>
52-
<td><FuelSavingsTextInput onChange={this.fuelSavingsKeypress} name="tradePpg" value={fuelSavings.tradePpg}/>
53-
</td>
54-
</tr>
55-
<tr>
56-
<td><label htmlFor="milesDriven">Miles Driven</label></td>
57-
<td>
58-
<FuelSavingsTextInput
59-
onChange={this.fuelSavingsKeypress}
60-
name="milesDriven"
61-
value={fuelSavings.milesDriven}/>
62-
miles per
63-
<select
64-
name="milesDrivenTimeframe"
65-
onChange={this.onTimeframeChange}
66-
value={fuelSavings.milesDrivenTimeframe}>
67-
<option value="week">Week</option>
68-
<option value="month">Month</option>
69-
<option value="year">Year</option>
70-
</select>
71-
</td>
72-
</tr>
73-
<tr>
74-
<td><label>Date Modified</label></td>
75-
<td>{fuelSavings.dateModified}</td>
76-
</tr>
35+
<tr>
36+
<td><label htmlFor="newMpg">New Vehicle MPG</label></td>
37+
<td><FuelSavingsTextInput onChange={this.fuelSavingsKeypress} name="newMpg" value={fuelSavings.newMpg}/>
38+
</td>
39+
</tr>
40+
<tr>
41+
<td><label htmlFor="tradeMpg">Trade-in MPG</label></td>
42+
<td><FuelSavingsTextInput onChange={this.fuelSavingsKeypress} name="tradeMpg" value={fuelSavings.tradeMpg}/>
43+
</td>
44+
</tr>
45+
<tr>
46+
<td><label htmlFor="newPpg">New Vehicle price per gallon</label></td>
47+
<td><FuelSavingsTextInput onChange={this.fuelSavingsKeypress} name="newPpg" value={fuelSavings.newPpg}/>
48+
</td>
49+
</tr>
50+
<tr>
51+
<td><label htmlFor="tradePpg">Trade-in price per gallon</label></td>
52+
<td><FuelSavingsTextInput onChange={this.fuelSavingsKeypress} name="tradePpg" value={fuelSavings.tradePpg}/>
53+
</td>
54+
</tr>
55+
<tr>
56+
<td><label htmlFor="milesDriven">Miles Driven</label></td>
57+
<td>
58+
<FuelSavingsTextInput
59+
onChange={this.fuelSavingsKeypress}
60+
name="milesDriven"
61+
value={fuelSavings.milesDriven}/>
62+
miles per
63+
<select
64+
name="milesDrivenTimeframe"
65+
onChange={this.onTimeframeChange}
66+
value={fuelSavings.milesDrivenTimeframe}>
67+
<option value="week">Week</option>
68+
<option value="month">Month</option>
69+
<option value="year">Year</option>
70+
</select>
71+
</td>
72+
</tr>
73+
<tr>
74+
<td><label>Date Modified</label></td>
75+
<td>{fuelSavings.dateModified}</td>
76+
</tr>
7777
</tbody>
7878
</table>
7979

@@ -85,11 +85,27 @@ class FuelSavingsForm extends React.Component {
8585
);
8686
}
8787
}
88+
const { func, shape, number, bool, string } = PropTypes;
8889

8990
FuelSavingsForm.propTypes = {
90-
saveFuelSavings: PropTypes.func.isRequired,
91-
calculateFuelSavings: PropTypes.func.isRequired,
92-
fuelSavings: PropTypes.object.isRequired
91+
saveFuelSavings: func.isRequired,
92+
calculateFuelSavings: func.isRequired,
93+
fuelSavings: shape({
94+
newMpg: number,
95+
tradeMpg: number,
96+
newPpg: number,
97+
tradePpg: number,
98+
milesDriven: number,
99+
milesDrivenTimeframe: string,
100+
displayResult: bool,
101+
dateModified: string,
102+
necessaryDataIsProvidedToCalculateSavings: bool,
103+
savings: shape({
104+
monthly: number,
105+
annual: number,
106+
threeYear: number,
107+
}),
108+
}).isRequired
93109
};
94110

95111
export default FuelSavingsForm;

src/components/FuelSavingsResults.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ const FuelSavingsResults = ({savings}) => {
1919
return (
2020
<table>
2121
<tbody>
22-
<tr>
23-
<td className="fuel-savings-label">{resultLabel}</td>
24-
<td>
22+
<tr>
23+
<td className="fuel-savings-label">{resultLabel}</td>
24+
<td>
2525
<table>
2626
<tbody>
2727
<tr>

src/components/FuelSavingsResults.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import {shallow} from 'enzyme';
2+
import { shallow } from 'enzyme';
33
import FuelSavingsResults from './FuelSavingsResults';
44

55
describe('<FuelSavingsResults />', () => {

src/components/FuelSavingsTextInput.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ const FuelSavingsTextInput = (props) => {
1616
);
1717
};
1818

19+
const { string, func, number, oneOfType } = PropTypes;
20+
1921
FuelSavingsTextInput.propTypes = {
20-
name: PropTypes.string.isRequired,
21-
onChange: PropTypes.func.isRequired,
22-
placeholder: PropTypes.string,
23-
value: PropTypes.oneOfType([
24-
PropTypes.string,
25-
PropTypes.number
22+
name: string.isRequired,
23+
onChange: func.isRequired,
24+
placeholder: string,
25+
value: oneOfType([
26+
string,
27+
number
2628
])
2729
};
2830

src/components/FuelSavingsTextInput.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import {shallow} from 'enzyme';
2+
import { shallow } from 'enzyme';
33
import FuelSavingsTextInput from './FuelSavingsTextInput';
44

55
describe('<FuelSavingsTextInput />', () => {

src/components/HomePage.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import {Link} from 'react-router';
2+
import { Link } from 'react-router-dom';
33

44
const HomePage = () => {
55
return (
@@ -8,7 +8,7 @@ const HomePage = () => {
88

99
<h2>Get Started</h2>
1010
<ol>
11-
<li>Review the <Link to="fuel-savings">demo app</Link></li>
11+
<li>Review the <Link to="/fuel-savings">demo app</Link></li>
1212
<li>Remove the demo and start coding: npm run remove-demo</li>
1313
</ol>
1414
</div>

src/components/NotFoundPage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { Link } from 'react-router';
2+
import { Link } from 'react-router-dom';
33

44
const NotFoundPage = () => {
55
return (

src/components/Root.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types';
3+
import { ConnectedRouter } from 'react-router-redux';
34
import { Provider } from 'react-redux';
4-
import routes from '../routes';
5-
import { Router } from 'react-router';
5+
import App from './App';
66

77
export default class Root extends Component {
88
render() {
99
const { store, history } = this.props;
1010
return (
1111
<Provider store={store}>
12-
<Router history={history} routes={routes} />
12+
<ConnectedRouter history={history}>
13+
<App />
14+
</ConnectedRouter>
1315
</Provider>
1416
);
1517
}

src/index.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,13 @@
22

33
import React from 'react';
44
import { render } from 'react-dom';
5-
import { browserHistory } from 'react-router';
65
import { AppContainer } from 'react-hot-loader';
6+
import configureStore, { history } from './store/configureStore';
77
import Root from './components/Root';
8-
9-
import configureStore from './store/configureStore';
10-
require('./favicon.ico'); // Tell webpack to load favicon.ico
118
import './styles/styles.scss'; // Yep, that's right. You can import SASS/CSS files too! Webpack will run the associated loader and plug this into the page.
12-
import { syncHistoryWithStore } from 'react-router-redux';
13-
9+
require('./favicon.ico'); // Tell webpack to load favicon.ico
1410
const store = configureStore();
1511

16-
// Create an enhanced history that syncs navigation events with the store
17-
const history = syncHistoryWithStore(browserHistory, store);
18-
19-
2012
render(
2113
<AppContainer>
2214
<Root store={store} history={history} />

src/reducers/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { combineReducers } from 'redux';
22
import fuelSavings from './fuelSavingsReducer';
3-
import {routerReducer} from 'react-router-redux';
3+
import { routerReducer } from 'react-router-redux';
44

55
const rootReducer = combineReducers({
66
fuelSavings,

src/store/configureStore.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import {createStore, compose, applyMiddleware} from 'redux';
22
import reduxImmutableStateInvariant from 'redux-immutable-state-invariant';
33
import thunk from 'redux-thunk';
4+
import createHistory from 'history/createBrowserHistory';
5+
// 'routerMiddleware': the new way of storing route changes with redux middleware since rrV4.
6+
import { routerMiddleware } from 'react-router-redux';
47
import rootReducer from '../reducers';
5-
8+
export const history = createHistory();
69
function configureStoreProd(initialState) {
10+
const reactRouterMiddleware = routerMiddleware(history);
711
const middlewares = [
812
// Add other middleware on this line...
913

1014
// thunk middleware can also accept an extra argument to be passed to each thunk action
1115
// https://github.com/gaearon/redux-thunk#injecting-a-custom-argument
1216
thunk,
17+
reactRouterMiddleware,
1318
];
1419

1520
return createStore(rootReducer, initialState, compose(
@@ -19,6 +24,7 @@ function configureStoreProd(initialState) {
1924
}
2025

2126
function configureStoreDev(initialState) {
27+
const reactRouterMiddleware = routerMiddleware(history);
2228
const middlewares = [
2329
// Add other middleware on this line...
2430

@@ -28,6 +34,7 @@ function configureStoreDev(initialState) {
2834
// thunk middleware can also accept an extra argument to be passed to each thunk action
2935
// https://github.com/gaearon/redux-thunk#injecting-a-custom-argument
3036
thunk,
37+
reactRouterMiddleware,
3138
];
3239

3340
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // add support for Redux dev tools
@@ -49,4 +56,4 @@ function configureStoreDev(initialState) {
4956

5057
const configureStore = process.env.NODE_ENV === 'production' ? configureStoreProd : configureStoreDev;
5158

52-
export default configureStore;
59+
export default configureStore;

0 commit comments

Comments
 (0)