Skip to content

Commit 47aefb1

Browse files
committed
Migrate real-world example to redux-react-router
1 parent 9bff38d commit 47aefb1

File tree

10 files changed

+103
-67
lines changed

10 files changed

+103
-67
lines changed

examples/real-world/components/Explore.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { Component, PropTypes, findDOMNode } from 'react';
1+
import React, { Component, PropTypes } from 'react';
2+
import { findDOMNode } from 'react-dom';
23

34
const GITHUB_REPO = 'https://github.com/rackt/redux';
45

examples/real-world/containers/App.js

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { Component, PropTypes } from 'react';
22
import { connect } from 'react-redux';
3+
import { pushState } from 'redux-react-router';
34
import Explore from '../components/Explore';
45
import { resetErrorMessage } from '../actions';
56

@@ -16,9 +17,7 @@ class App extends Component {
1617
}
1718

1819
handleChange(nextValue) {
19-
// Available thanks to contextTypes below
20-
const { history } = this.context;
21-
history.pushState(null, `/${nextValue}`);
20+
this.props.pushState(null, `/${nextValue}`);
2221
}
2322

2423
renderErrorMessage() {
@@ -40,14 +39,10 @@ class App extends Component {
4039
}
4140

4241
render() {
43-
// Injected by React Router
44-
const { location, children } = this.props;
45-
const { pathname } = location;
46-
const value = pathname.substring(1);
47-
42+
const { children, inputValue } = this.props;
4843
return (
4944
<div>
50-
<Explore value={value}
45+
<Explore value={inputValue}
5146
onChange={this.handleChange} />
5247
<hr />
5348
{this.renderErrorMessage()}
@@ -58,29 +53,23 @@ class App extends Component {
5853
}
5954

6055
App.propTypes = {
56+
// Injected by React Redux
6157
errorMessage: PropTypes.string,
6258
resetErrorMessage: PropTypes.func.isRequired,
63-
location: PropTypes.shape({
64-
pathname: PropTypes.string.isRequired
65-
}),
66-
params: PropTypes.shape({
67-
userLogin: PropTypes.string,
68-
repoName: PropTypes.string
69-
}).isRequired,
59+
pushState: PropTypes.func.isRequired,
60+
inputValue: PropTypes.string.isRequired,
61+
// Injected by React Router
7062
children: PropTypes.node
7163
};
7264

73-
App.contextTypes = {
74-
history: PropTypes.object.isRequired
75-
};
76-
7765
function mapStateToProps(state) {
7866
return {
79-
errorMessage: state.errorMessage
67+
errorMessage: state.errorMessage,
68+
inputValue: state.router.location.pathname.substring(1)
8069
};
8170
}
8271

83-
export default connect(
84-
mapStateToProps,
85-
{ resetErrorMessage }
86-
)(App);
72+
export default connect(mapStateToProps, {
73+
resetErrorMessage,
74+
pushState
75+
})(App);

examples/real-world/containers/RepoPage.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,15 @@ RepoPage.propTypes = {
6565
repo: PropTypes.object,
6666
fullName: PropTypes.string.isRequired,
6767
name: PropTypes.string.isRequired,
68-
owner: PropTypes.object.isRequired,
68+
owner: PropTypes.object,
6969
stargazers: PropTypes.array.isRequired,
7070
stargazersPagination: PropTypes.object,
7171
loadRepo: PropTypes.func.isRequired,
7272
loadStargazers: PropTypes.func.isRequired
7373
};
7474

75-
function mapStateToProps(state, ownProps) {
76-
const { login, name } = ownProps.params;
75+
function mapStateToProps(state) {
76+
const { login, name } = state.router.params;
7777
const {
7878
pagination: { stargazersByRepo },
7979
entities: { users, repos }
@@ -93,7 +93,7 @@ function mapStateToProps(state, ownProps) {
9393
};
9494
}
9595

96-
export default connect(
97-
mapStateToProps,
98-
{ loadRepo, loadStargazers }
99-
)(RepoPage);
96+
export default connect(mapStateToProps, {
97+
loadRepo,
98+
loadStargazers
99+
})(RepoPage);

examples/real-world/containers/UserPage.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ UserPage.propTypes = {
7272
loadStarred: PropTypes.func.isRequired
7373
};
7474

75-
function mapStateToProps(state, ownProps) {
76-
const { login } = ownProps.params;
75+
function mapStateToProps(state) {
76+
const { login } = state.router.params;
7777
const {
7878
pagination: { starredByUser },
7979
entities: { users, repos }
@@ -92,7 +92,7 @@ function mapStateToProps(state, ownProps) {
9292
};
9393
}
9494

95-
export default connect(
96-
mapStateToProps,
97-
{ loadUser, loadStarred }
98-
)(UserPage);
95+
export default connect(mapStateToProps, {
96+
loadUser,
97+
loadStarred
98+
})(UserPage);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react';
2+
import { render } from 'react-dom';
3+
import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
4+
5+
/**
6+
* Puts Redux DevTools into a separate window.
7+
* Based on https://gist.github.com/tlrobinson/1e63d15d3e5f33410ef7#gistcomment-1560218.
8+
*/
9+
export default function createDevToolsWindow(store) {
10+
// Give it a name so it reuses the same window.
11+
const win = window.open(
12+
null,
13+
'Redux DevTools',
14+
'menubar=no,location=no,resizable=yes,scrollbars=no,status=no'
15+
);
16+
17+
// Reload in case it's reusing the same window with the old content.
18+
win.location.reload();
19+
20+
// Wait a little bit for it to reload, then render.
21+
setTimeout(() => render(
22+
<DebugPanel top right bottom left>
23+
<DevTools store={store} monitor={LogMonitor} />
24+
</DebugPanel>,
25+
win.document.body
26+
), 10);
27+
}

examples/real-world/index.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
11
import 'babel-core/polyfill';
22
import React from 'react';
3-
import createBrowserHistory from 'history/lib/createBrowserHistory';
3+
import { render } from 'react-dom';
44
import { Provider } from 'react-redux';
5-
import { Router, Route } from 'react-router';
5+
import { ReduxRouter } from 'redux-react-router';
66
import configureStore from './store/configureStore';
7-
import App from './containers/App';
8-
import UserPage from './containers/UserPage';
9-
import RepoPage from './containers/RepoPage';
107

11-
const history = createBrowserHistory();
128
const store = configureStore();
139

14-
React.render(
10+
render(
1511
<Provider store={store}>
16-
{() =>
17-
<Router history={history}>
18-
<Route path="/" component={App}>
19-
<Route path="/:login/:name"
20-
component={RepoPage} />
21-
<Route path="/:login"
22-
component={UserPage} />
23-
</Route>
24-
</Router>
25-
}
12+
<ReduxRouter />
2613
</Provider>,
2714
document.getElementById('root')
2815
);
16+
17+
if (process.env.NODE_ENV !== 'production') {
18+
// Use require because imports can't be conditional.
19+
// In production, you should ensure process.env.NODE_ENV
20+
// is envified so that Uglify can eliminate this
21+
// module and its dependencies as dead code.
22+
require('./createDevToolsWindow')(store);
23+
}

examples/real-world/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,20 @@
2020
"isomorphic-fetch": "^2.1.1",
2121
"lodash": "^3.10.1",
2222
"normalizr": "^1.0.0",
23-
"react": "^0.13.3",
23+
"react": "^0.14.0-rc1",
24+
"react-dom": "^0.14.0-rc1",
2425
"react-redux": "^2.1.2",
2526
"react-router": "^1.0.0-rc1",
2627
"redux": "^3.0.0",
2728
"redux-logger": "0.0.1",
29+
"redux-react-router": "^1.0.0-beta1",
2830
"redux-thunk": "^0.1.0"
2931
},
3032
"devDependencies": {
3133
"babel-core": "^5.6.18",
3234
"babel-loader": "^5.1.4",
3335
"react-hot-loader": "^1.3.0",
36+
"redux-devtools": "^2.1.2",
3437
"webpack": "^1.9.11",
3538
"webpack-dev-server": "^1.9.0"
3639
}

examples/real-world/reducers/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as ActionTypes from '../actions';
22
import merge from 'lodash/object/merge';
33
import paginate from './paginate';
4+
import { routerStateReducer as router } from 'redux-react-router';
45
import { combineReducers } from 'redux';
56

67
// Updates an entity cache in response to any action with response.entities.
@@ -48,7 +49,8 @@ const pagination = combineReducers({
4849
const rootReducer = combineReducers({
4950
entities,
5051
pagination,
51-
errorMessage
52+
errorMessage,
53+
router
5254
});
5355

5456
export default rootReducer;

examples/real-world/routes.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react';
2+
import { Route } from 'react-router';
3+
import App from './containers/App';
4+
import UserPage from './containers/UserPage';
5+
import RepoPage from './containers/RepoPage';
6+
7+
export default (
8+
<Route path="/" component={App}>
9+
<Route path="/:login/:name"
10+
component={RepoPage} />
11+
<Route path="/:login"
12+
component={UserPage} />
13+
</Route>
14+
);

examples/real-world/store/configureStore.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
import { createStore, applyMiddleware } from 'redux';
2-
import thunkMiddleware from 'redux-thunk';
3-
import apiMiddleware from '../middleware/api';
4-
import loggerMiddleware from 'redux-logger';
1+
import { createStore, applyMiddleware, compose } from 'redux';
2+
import { reduxReactRouter } from 'redux-react-router';
3+
import { devTools } from 'redux-devtools';
4+
import createHistory from 'history/lib/createBrowserHistory';
5+
import routes from '../routes';
6+
import thunk from 'redux-thunk';
7+
import api from '../middleware/api';
8+
import logger from 'redux-logger';
59
import rootReducer from '../reducers';
610

7-
const createStoreWithMiddleware = applyMiddleware(
8-
thunkMiddleware,
9-
apiMiddleware,
10-
loggerMiddleware
11+
const finalCreateStore = compose(
12+
applyMiddleware(thunk, api),
13+
reduxReactRouter({ routes, createHistory }),
14+
applyMiddleware(logger),
15+
devTools()
1116
)(createStore);
1217

1318
export default function configureStore(initialState) {
14-
const store = createStoreWithMiddleware(rootReducer, initialState);
19+
const store = finalCreateStore(rootReducer, initialState);
1520

1621
if (module.hot) {
1722
// Enable Webpack hot module replacement for reducers

0 commit comments

Comments
 (0)