Skip to content

Commit 3682d4f

Browse files
author
nostophilia
committed
Revise "Hello World" Redux example
1 parent 5e5b92e commit 3682d4f

File tree

11 files changed

+74
-140
lines changed

11 files changed

+74
-140
lines changed

lib/generators/react_on_rails/react_with_redux_generator.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def copy_base_redux_files
1616
%w(client/app/bundles/HelloWorld/actions/helloWorldActionCreators.jsx
1717
client/app/bundles/HelloWorld/containers/HelloWorld.jsx
1818
client/app/bundles/HelloWorld/constants/helloWorldConstants.jsx
19-
client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx
19+
client/app/bundles/HelloWorld/reducers/name.jsx
2020
client/app/bundles/HelloWorld/reducers/index.jsx
2121
client/app/bundles/HelloWorld/store/helloWorldStore.jsx).each do |file|
2222
copy_file(base_path + file, file)

lib/generators/react_on_rails/templates/base/base/client/app/bundles/HelloWorld/components/HelloWorldWidget.jsx.tt

+28-34
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,33 @@
44
import React, { PropTypes } from 'react';
55

66
// Simple example of a React "dumb" component
7-
export default class HelloWorldWidget extends React.Component {
8-
static propTypes = {
9-
// If you have lots of data or action properties, you should consider grouping them by
10-
// passing two properties: "data" and "actions".
11-
updateName: PropTypes.func.isRequired,
12-
name: PropTypes.string.isRequired,
13-
};
7+
const HelloWorldWidget = (props) => {
8+
const { name, updateName } = props;
149

15-
// React will automatically provide us with the event `e`
16-
handleChange(e) {
17-
const name = e.target.value;
18-
this.props.updateName(name);
19-
}
10+
return (
11+
<div className="container">
12+
<h3>
13+
Hello, {name}!
14+
</h3>
15+
<hr />
16+
<form className="form-horizontal">
17+
<label htmlFor="name">
18+
Say hello to:
19+
</label>
20+
<input
21+
type="text" value={name} id="name"
22+
onChange={(e) => updateName(e.target.value)}
23+
/>
24+
</form>
25+
</div>
26+
);
27+
};
2028

21-
render() {
22-
const { name } = this.props;
23-
return (
24-
<div className="container">
25-
<h3>
26-
Hello, {name}!
27-
</h3>
28-
<hr />
29-
<form className="form-horizontal">
30-
<label>
31-
Say hello to:
32-
</label>
33-
<input
34-
type="text"
35-
value={name}
36-
onChange={e => this.handleChange(e)}
37-
/>
38-
</form>
39-
</div>
40-
);
41-
}
42-
}
29+
HelloWorldWidget.propTypes = {
30+
// If you have lots of data or action properties, you should consider grouping them by
31+
// passing two properties: "data" and "actions".
32+
updateName: PropTypes.func.isRequired,
33+
name: PropTypes.string.isRequired,
34+
};
35+
36+
export default HelloWorldWidget;

lib/generators/react_on_rails/templates/base/base/client/package.json.tt

-5
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
"babel-preset-stage-0": "^6.5.0",
2525
"es5-shim": "^4.5.7",
2626
"expose-loader": "^0.7.1",
27-
<%- if options.redux? -%>
28-
"immutable": "^3.7.6",
29-
<%- end -%>
3027
"imports-loader": "^0.6.5",
3128
<%- if options.redux? -%>
3229
"mirror-creator": "1.1.0",
@@ -37,8 +34,6 @@
3734
<%- if options.redux? -%>
3835
"react-redux": "^4.4.1",
3936
"redux": "^3.3.1",
40-
"redux-promise": "^0.5.3",
41-
"redux-thunk": "^2.0.1",
4237
<%- end -%>
4338
"webpack": "^1.12.14"
4439
},
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import actionTypes from '../constants/helloWorldConstants';
22

3-
export function updateName(name) {
4-
return {
5-
type: actionTypes.HELLO_WORLD_NAME_UPDATE,
6-
name,
7-
};
8-
}
3+
export const updateName = (text) => ({
4+
type: actionTypes.HELLO_WORLD_NAME_UPDATE,
5+
text,
6+
});
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,27 @@
11
import React, { PropTypes } from 'react';
2-
import HelloWorldWidget from '../components/HelloWorldWidget';
32
import { connect } from 'react-redux';
4-
import { bindActionCreators } from 'redux';
5-
import Immutable from 'immutable';
6-
import * as helloWorldActionCreators from '../actions/helloWorldActionCreators';
3+
import HelloWorldWidget from '../components/HelloWorldWidget';
4+
import * as actions from '../actions/helloWorldActionCreators';
75

8-
function select(state) {
9-
// Which part of the Redux global state does our component want to receive as props?
10-
// Note the use of `$$` to prefix the property name because the value is of type Immutable.js
11-
return { $$helloWorldStore: state.$$helloWorldStore };
12-
}
6+
// Which part of the Redux global state does our component want to receive as props?
7+
const mapStateToProps = (state) => ({ name: state.name });
138

149
// Simple example of a React "smart" component
1510
const HelloWorld = (props) => {
16-
const { dispatch, $$helloWorldStore } = props;
17-
const actions = bindActionCreators(helloWorldActionCreators, dispatch);
18-
const { updateName } = actions;
19-
const name = $$helloWorldStore.get('name');
11+
const { name, updateName } = props;
2012

2113
// This uses the ES2015 spread operator to pass properties as it is more DRY
2214
// This is equivalent to:
23-
// <HelloWorldWidget $$helloWorldStore={$$helloWorldStore} actions={actions} />
24-
return (
25-
<HelloWorldWidget {...{ updateName, name }} />
26-
);
15+
// <HelloWorldWidget name={name} updateName={updateName} />
16+
return <HelloWorldWidget {...{ name, updateName }} />;
2717
};
2818

2919
HelloWorld.propTypes = {
30-
dispatch: PropTypes.func.isRequired,
31-
32-
// This corresponds to the value used in function select above.
33-
// We prefix all property and variable names pointing to Immutable.js objects with '$$'.
34-
// This allows us to immediately know we don't call $$helloWorldStore['someProperty'], but
35-
// instead use the Immutable.js `get` API for Immutable.Map
36-
$$helloWorldStore: PropTypes.instanceOf(Immutable.Map).isRequired,
20+
name: PropTypes.string.isRequired,
21+
updateName: PropTypes.func.isRequired,
3722
};
3823

3924
// Don't forget to actually use connect!
4025
// Note that we don't export HelloWorld, but the redux "connected" version of it.
4126
// See https://github.com/reactjs/react-redux/blob/master/docs/api.md#examples
42-
export default connect(select)(HelloWorld);
27+
export default connect(mapStateToProps, actions)(HelloWorld);

lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx

-19
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1+
import { combineReducers } from 'redux';
2+
13
// This file is our manifest of all reducers for the app.
24
// See also /client/app/bundles/HelloWorld/store/helloWorldStore.jsx
35
// A real world app will likely have many reducers and it helps to organize them in one file.
4-
import helloWorldReducer from './helloWorldReducer';
5-
import { $$initialState as $$helloWorldState } from './helloWorldReducer';
6-
7-
export default {
8-
$$helloWorldStore: helloWorldReducer,
9-
};
6+
import name from './name';
107

11-
export const initialStates = {
12-
$$helloWorldState,
13-
};
8+
export default combineReducers({ name });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import actionTypes from '../constants/helloWorldConstants';
2+
3+
const name = (state = '', action) => {
4+
const { type, text } = action;
5+
6+
switch (type) {
7+
case actionTypes.HELLO_WORLD_NAME_UPDATE:
8+
return text;
9+
default:
10+
return state;
11+
}
12+
};
13+
14+
export default name;

lib/generators/react_on_rails/templates/redux/base/client/app/bundles/HelloWorld/startup/HelloWorldApp.jsx.tt

+6-10
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,19 @@ import React from 'react';
22
import ReactOnRails from 'react-on-rails';
33
import { Provider } from 'react-redux';
44

5-
import createStore from '../store/helloWorldStore';
5+
import configureStore from '../store/helloWorldStore';
66
import HelloWorld from '../containers/HelloWorld';
77

88
// See documentation for https://github.com/reactjs/react-redux.
99
// This is how you get props from the Rails view into the redux store.
1010
// This code here binds your smart component to the redux store.
1111
// railsContext provides contextual information especially useful for server rendering, such as
1212
// knowing the locale. See the React on Rails documentation for more info on the railsContext
13-
const HelloWorldApp = (props, _railsContext) => {
14-
const store = createStore(props);
15-
const reactComponent = (
16-
<Provider store={store}>
17-
<HelloWorld />
18-
</Provider>
19-
);
20-
return reactComponent;
21-
};
13+
const HelloWorldApp = (props, _railsContext) => (
14+
<Provider store={configureStore(props)}>
15+
<HelloWorld />
16+
</Provider>
17+
);
2218

2319
// This is how react_on_rails can see the HelloWorldApp in the browser.
2420
ReactOnRails.register({ HelloWorldApp });
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,8 @@
1-
import { compose, createStore, applyMiddleware, combineReducers } from 'redux';
1+
import { createStore } from 'redux';
2+
import rootReducer from '../reducers/index';
23

3-
// See
4-
// https://github.com/gaearon/redux-thunk and http://redux.js.org/docs/advanced/AsyncActions.html
5-
// This is not actually used for this simple example, but you'd probably want to use this
6-
// once your app has asynchronous actions.
7-
import thunkMiddleware from 'redux-thunk';
4+
const configureStore = (railsProps) => (
5+
createStore(rootReducer, railsProps)
6+
);
87

9-
import reducers from '../reducers';
10-
import { initialStates } from '../reducers';
11-
12-
export default props => {
13-
// This is how we get initial props Rails into redux.
14-
const { name } = props;
15-
const { $$helloWorldState } = initialStates;
16-
17-
// Redux expects to initialize the store using an Object, not an Immutable.Map
18-
const initialState = {
19-
$$helloWorldStore: $$helloWorldState.merge({
20-
name,
21-
}),
22-
};
23-
24-
const reducer = combineReducers(reducers);
25-
const composedStore = compose(
26-
applyMiddleware(thunkMiddleware)
27-
);
28-
const storeCreator = composedStore(createStore);
29-
const store = storeCreator(reducer, initialState);
30-
31-
return store;
32-
};
8+
export default configureStore;

spec/react_on_rails/support/shared_examples/react_with_redux_generator_examples.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
%w(client/app/bundles/HelloWorld/actions/helloWorldActionCreators.jsx
88
client/app/bundles/HelloWorld/containers/HelloWorld.jsx
99
client/app/bundles/HelloWorld/constants/helloWorldConstants.jsx
10-
client/app/bundles/HelloWorld/reducers/helloWorldReducer.jsx
10+
client/app/bundles/HelloWorld/reducers/name.jsx
1111
client/app/bundles/HelloWorld/reducers/index.jsx
1212
client/app/bundles/HelloWorld/store/helloWorldStore.jsx
1313
client/app/bundles/HelloWorld/startup/HelloWorldApp.jsx).each { |file| assert_file(file) }

0 commit comments

Comments
 (0)