Skip to content

Commit b12e11a

Browse files
committed
Action sub generator now working. Readme updated with documentation on subgenerators.
1 parent 2958ebb commit b12e11a

File tree

7 files changed

+240
-27
lines changed

7 files changed

+240
-27
lines changed

Diff for: README.md

+196-15
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,213 @@
11
# generator-webpack-redux-react
22

3+
34
Generator for a webpack-redux-react project with sub-generators for Components, Containers(Redux linked component), as well as Redux Actions and Reducers.
45

6+
57
## Getting Started
8+
1. Install yeoman if you don't have it: using `npm install -g yo`
9+
10+
1. Install Generator: `npm install -g generator-webpack-redux-react`
11+
12+
13+
## Creating a project
14+
1. Create a project folder and enter it:
15+
`mkdir myProject && cd myProject`
16+
17+
2. Initiate the generator:
18+
```yo webpack-redux-react```
19+
20+
21+
22+
## Sub generators
23+
### Generated files based on [Redux Examples](https://github.com/rackt/redux)
24+
25+
26+
#### Component
27+
28+
To create a react component class named *Test* run: `yo webpack-redux-react:component Car`
29+
30+
Creates a folder within `/components` that matches the name provided. Below is the result of the command above being run:
31+
32+
```
33+
/components
34+
--/Car
35+
----Car.js
36+
----Car.scss
37+
```
38+
/components/Car.js:
39+
```javascript
40+
import React, {Component, PropTypes} from 'react';
41+
import './Car.scss';
42+
43+
class Car extends Component {
44+
constructor(props){
45+
super(props);
46+
}
47+
render(){
48+
return (
49+
<div className="Car">
50+
51+
</div>
52+
);
53+
}
54+
}
55+
56+
export default Car
57+
```
58+
59+
### Redux specific
60+
#### Container
61+
**NOTE:** Containers are synonymous with *Smart Components* and *Linked-State Components*
62+
63+
To create a container named *Cars* run: `yo webpack-redux-react:container Cars`
664

7-
Before:
8-
* Install yeoman if you don't have it:
9-
```bash
10-
npm install -g yo
65+
Creates a folder within `/containers` that matches the name provided. Below is the result of the command above being run:
66+
67+
```
68+
/conatiners
69+
--/Cars
70+
----Cars.js
71+
----Cars.scss
1172
```
1273

13-
1. Install Generator:
74+
containers/Cars.js:
75+
```javascript
76+
import React, {Component, PropTypes} from 'react';
77+
import {bindActionCreators} from 'redux';
78+
import {connect} from 'react-redux';
79+
80+
import * as Actions from '../../actions/cars';
81+
import './Cars.scss';
82+
83+
class Cars extends Component {
84+
constructor(props){
85+
super(props);
86+
}
87+
static propTypes = {
88+
89+
};
90+
render(){
91+
return (
92+
<div className="Cars">
93+
</div>
94+
);
95+
}
96+
}
97+
//Place state of redux store into props of component
98+
function mapStateToProps(state) {
99+
return {
100+
account: state.account,
101+
router: state.router
102+
};
103+
}
104+
//Place action methods into props
105+
function mapDispatchToProps(dispatch) {
106+
return bindActionCreators(Actions, dispatch);
107+
}
108+
export default connect(mapStateToProps, mapDispatchToProps)(Cars);
14109

15-
```bash
16-
npm install -g generator-webpack-redux-react
17110
```
18-
2. Create a project folder and enter it:
19111

20-
```bash
21-
mkdir myProject && cd myProject
112+
#### Action
113+
[Actions](http://redux.js.org/docs/basics/Actions.html) are functions that are called from containers to make something happen to the state (i.e add a car).
114+
To create a set of actions (add, update, remove) for cars run: `yo webpack-redux-react:action cars`
115+
116+
Creates a folder within `/actions` that matches the name provided. Below is the result of the command above being run:
117+
22118
```
119+
/actions
120+
--cars.js
121+
```
122+
123+
**/actions/cars.js**
124+
```javascript
125+
export const ADD_CARS = 'ADD_CARS';
126+
export const REMOVE_CARS = 'REMOVE_CARS';
127+
export const UPDATE_CARS = 'UPDATE_CARS';
128+
129+
export function addCars(cars) {
130+
return {
131+
type: 'ADD_CARS',
132+
payload: 'cars'
133+
};
134+
}
135+
export function removeCars(cars) {
136+
return {
137+
type: 'REMOVE_CARS',
138+
payload: 'cars'
139+
};
140+
}
141+
export function updateCars(cars) {
142+
return {
143+
type: 'UPDATE_CARS',
144+
payload: 'cars'
145+
};
146+
}
147+
148+
```
149+
150+
#### Reducer
151+
[Reducers](http://redux.js.org/docs/basics/Reducers.html) listen for actions and modify specific pieces of the state accordingly. In this example we are creating a cars reducer that manages state.cars, which is stored as an array.
152+
`yo webpack-redux-react:reducer cars` then select array
153+
```
154+
/reducers
155+
--cars.js
156+
```
157+
158+
**reducers/cars.js**:
23159

24-
3.Initiate the generator:
160+
```javascript
161+
import {
162+
ADD_CAR,
163+
UPDATE_CAR,
164+
REMOVE_CAR,
165+
} from '../actions/cars';
166+
import {union, clone} from 'lodash';
167+
export default function cars(state = [], action) {
168+
switch (action.type) {
169+
case ADD_CAR:
170+
if(!action.payload){
171+
console.error('Payload required to add a cars');
172+
return state;
173+
}
174+
return [...state, action.payload];
175+
break;
176+
case UPDATE_CAR:
177+
if(!action.index && action.payload){
178+
console.error('Index and payload required to update a cars');
179+
return state;
180+
}
181+
if(!state[action.name]){
182+
console.error('cars with that name already exists');
183+
return state;
184+
}
185+
let newState = clone(state);
186+
newState[action.index] = action.payload;
187+
return newState;
188+
break;
189+
case REMOVE_CAR:
190+
if(!action.index){
191+
console.error('Index required to delete a cars');
192+
return state;
193+
}
194+
if(!state[action.index]){
195+
console.error('cars at that index does not exist');
196+
return state;
197+
}
198+
let newState = clone(state);
199+
delete newState[action.index];
200+
return newState;
201+
break;
202+
default:
203+
return state;
204+
}
205+
}
25206

26-
```bash
27-
yo webpack-redux-react
28207
```
29208

30-
## License
209+
## Other Reading
210+
* ###[Redux Docs](http://redux.js.org/)
211+
* ### [Redux Examples](https://github.com/rackt/redux/tree/master/examples)
31212

32-
MIT
213+
### Special thanks to [gaearon](https://github.com/gaearon) and [the rackt team](https://github.com/rackt) for building [redux](https://github.com/rackt/redux), and [redux router](https://github.com/rackt/redux-router)

Diff for: generators/action/index.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22
var yeoman = require('yeoman-generator');
3+
var _ = require('lodash');
4+
var chalk = require('chalk');
35

46
module.exports = yeoman.generators.Base.extend({
57
initializing: function () {
@@ -8,14 +10,11 @@ module.exports = yeoman.generators.Base.extend({
810
type: String,
911
desc: 'The subgenerator name'
1012
});
11-
12-
this.log('You called the WebpackReduxReact subgenerator with the argument ' + this.name + '.');
13+
this.capsName = this.name.toUpperCase();
14+
this.camelName = _.capitalize(this.name);
1315
},
1416

1517
writing: function () {
16-
this.fs.copy(
17-
this.templatePath('somefile.js'),
18-
this.destinationPath('somefile.js')
19-
);
18+
this.template('_main.js', 'actions/' + this.name.toLowerCase() + '.js', this.templateContext);
2019
}
2120
});

Diff for: generators/action/templates/_main.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export const ADD_<%= capsName %> = 'ADD_<%= capsName %>';
2+
export const REMOVE_<%= capsName %> = 'REMOVE_<%= capsName %>';
3+
export const UPDATE_<%= capsName %> = 'UPDATE_<%= capsName %>';
4+
5+
export function add<%= camelName %>(<%= name.toLowerCase() %>) {
6+
return {
7+
type: 'ADD_<%= capsName %>',
8+
payload: '<%= name.toLowerCase() %>'
9+
};
10+
}
11+
export function remove<%= camelName %>(<%= name.toLowerCase() %>) {
12+
return {
13+
type: 'REMOVE_<%= capsName %>',
14+
payload: '<%= name.toLowerCase() %>'
15+
};
16+
}
17+
export function update<%= camelName %>(<%= name.toLowerCase() %>) {
18+
return {
19+
type: 'UPDATE_<%= capsName %>',
20+
payload: '<%= name.toLowerCase() %>'
21+
};
22+
}

Diff for: generators/action/templates/somefile.js

-1
This file was deleted.

Diff for: generators/component/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module.exports = yeoman.generators.Base.extend({
1010
desc: 'The subgenerator name'
1111
});
1212

13-
this.log('You called the Component subgenerator with the argument ' + this.name + '.');
13+
// this.log('You called the Component subgenerator with the argument ' + this.name + '.');
1414
},
1515
prompting: function () {
1616
var done = this.async();

Diff for: generators/container/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = yeoman.generators.Base.extend({
1212
});
1313
this.capsName = _.capitalize(this.name);
1414
this.camelName = this.name.toLowerCase().charAt(0).toUpperCase().slice(1); //Capitalize first letter only
15-
// this.log('You called the Component subgenerator with the argument ' + this.name + '.');
15+
// this.log('You called the Container subgenerator with the argument ' + this.name + '.');
1616
},
1717
prompting: function () {
1818
var done = this.async();

Diff for: generators/container/templates/_main.js

+15-3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ import React, {Component, PropTypes} from 'react';
22
import {bindActionCreators} from 'redux';
33
import {connect} from 'react-redux';
44

5-
import * as Actions from '../../actions/<%= name %>';
5+
import * as Actions from '../../actions/<%= name.toLowerCase() %>';
66
import './<%= name %>.scss';
77

88
class <%= name %> extends Component {
99
constructor(props){
1010
super(props);
1111
}
12+
static propTypes = {
13+
14+
};
1215
render(){
1316
return (
1417
<div className="<%= name %>">
@@ -17,5 +20,14 @@ class <%= name %> extends Component {
1720
);
1821
}
1922
}
20-
21-
export default <%= name %>
23+
//Place state of redux store into props of component
24+
function mapStateToProps(state) {
25+
return {
26+
router: state.router
27+
};
28+
}
29+
//Place action methods into props
30+
function mapDispatchToProps(dispatch) {
31+
return bindActionCreators(Actions, dispatch);
32+
}
33+
export default connect(mapStateToProps, mapDispatchToProps)(<%= name %>);

0 commit comments

Comments
 (0)