Skip to content

Commit 7cdb67c

Browse files
committed
step 6 outline
1 parent d010992 commit 7cdb67c

File tree

12 files changed

+153
-42
lines changed

12 files changed

+153
-42
lines changed

README.md

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ A [CodeRoad](https://coderoad.github.io) tutorial for learning Redux.
66
<!-- @import('02') -->
77
<!-- @import('03') -->
88
<!-- @import('04') -->
9-
<!-- @import('06') -->
9+
<!-- @import('05') -->
1010
<!-- @import('07') -->
1111
<!-- @import('08') -->
1212
<!-- @import('09') -->
@@ -28,21 +28,6 @@ CodeRoad is an open-sourced interactive tutorial platform for the Atom Editor. L
2828

2929
## Outline
3030

31-
##### Pure Functions
31+
##### Combine Reducers
3232

33-
Reducers must be pure functions
34-
35-
State is "read only".
36-
37-
Notes
38-
```js
39-
const nextPokemon = state.pokemon.map(p => {
40-
if (id === p.id) {
41-
p.votes += 1;
42-
}
43-
return p;
44-
});
45-
return {
46-
pokemon: nextPokemon
47-
};
48-
```
33+
Create modular, composable reducers.

coderoad.json

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,66 @@
11
{
22
"info": {
33
"title": "CodeRoad Redux JS Tutorial",
4-
"description": "A [CodeRoad](https://coderoad.github.io) tutorial for learning Redux.\n\n<!-- @import('01') -->\n<!-- @import('02') -->\n<!-- @import('03') -->\n<!-- @import('04') -->\n<!-- @import('06') -->\n<!-- @import('07') -->\n<!-- @import('08') -->\n<!-- @import('09') -->"
4+
"description": "A [CodeRoad](https://coderoad.github.io) tutorial for learning Redux.\n\n<!-- @import('01') -->\n<!-- @import('02') -->\n<!-- @import('03') -->\n<!-- @import('04') -->\n<!-- @import('05') -->\n<!-- @import('07') -->\n<!-- @import('08') -->\n<!-- @import('09') -->"
55
},
66
"pages": [
77
{
8-
"title": "Pure Functions",
9-
"description": "Reducers must be pure functions\n\nState is \"read only\".\n\nNotes\n```js\nconst nextPokemon = state.pokemon.map(p => {\n if (id === p.id) {\n p.votes += 1;\n }\n return p;\n });\n return {\n pokemon: nextPokemon\n };\n ```",
8+
"title": "Combine Reducers",
9+
"description": "Create modular, composable reducers.",
1010
"tasks": [
1111
{
12-
"description": "Return a new list of Pokemon after incrementing \"votes\" of the pokemon with the matching \"id\"",
12+
"description": "import `combineReducers` from redux",
1313
"tests": [
14-
"05/01"
14+
"06/01"
15+
],
16+
"hints": [
17+
"Try this: `import { combineReducers } from 'redux';`"
1518
]
1619
},
1720
{
18-
"description": "Let's make a test to see that we are truly returning a new state. Wrap your `initialState` object in a `Object.freeze`. Freeze makes an object unchangeable. And yet your reducer should still work.",
21+
"description": "create a new `const reducers` and set it to \"reducer\". Pass \"reducers\" into your store for now, instead of \"reducer\". We'll use combineReducers shortly, but let's not break the app yet.",
1922
"tests": [
20-
"05/02"
23+
"06/02"
2124
]
2225
},
2326
{
24-
"description": "What if we were dealing with multiple keys on the state. We'd have to ensure that our changes return a complete new state each time. Use `Object.assign`",
27+
"description": "We're going to create more than one reducer. They can't all be called \"reducer\", so rename your reducer 'pokemon'.",
2528
"tests": [
26-
"05/03"
27-
],
28-
"hints": [
29-
"return `Object.assign({}, { pokemon: nextPokemon });`"
29+
"06/03"
30+
]
31+
},
32+
{
33+
"description": "combineReducers(), and pass in your reducer ({ pokemon })",
34+
"tests": [
35+
"06/04"
36+
]
37+
},
38+
{
39+
"description": "create a \"defaultPokemon\" state",
40+
"tests": [
41+
"06/05"
42+
]
43+
},
44+
{
45+
"description": "set the initial state of the store to an empty object",
46+
"tests": [
47+
"06/06"
48+
]
49+
},
50+
{
51+
"description": "pass the default state into the pokemon reducer",
52+
"tests": [
53+
"06/07"
54+
]
55+
},
56+
{
57+
"description": "We no longer pass the entire \"state\" inside of our reducers, only the slice of our state the reducer needs to know. Rename all references to \"state\" inside of your \"pokemon\" reducer to what it really is now: \"pokemon\".",
58+
"tests": [
59+
"06/08"
3060
]
3161
}
3262
],
33-
"onPageComplete": "Now that you have an idea of how reducers work. Next we can look at how to create multiple, modular reducers."
63+
"onPageComplete": "The state remains the same as before, but now"
3464
}
3565
]
3666
}

tutorial/06/01.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var expect = require('chai').expect;
2+
3+
/// load('index.js')
4+
5+
describe('01 combineReducers', () => {
6+
7+
it('should be loaded', () => {
8+
expect(combineReducers).to.be.defined;
9+
});
10+
11+
});

tutorial/06/02.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('02 reducers', () => {
2+
3+
it('doesn\'t exist', () => {
4+
expect(reducers).to.be.defined;
5+
});
6+
7+
it('should be set to "reducer"', () => {
8+
if (process.env.TASK_POSITION === '2') {
9+
expect(reducers).to.equal(reducer);
10+
}
11+
});
12+
13+
});

tutorial/06/03.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
describe('03 reducer', () => {
2+
3+
it('should be renamed "pokemon"', () => {
4+
expect(reducer).not.to.be.defined;
5+
expect(pokemon).to.be.defined;
6+
});
7+
8+
});

tutorial/06/04.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
describe('04 reducers', () => {
2+
3+
it('should be a new const', () => {
4+
expect(reducers).to.be.defined;
5+
});
6+
7+
it('should call "combineReducers" with { pokemon }', () => {
8+
// expect(reducers)
9+
});
10+
11+
});

tutorial/06/05.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
describe('05 defaultPokemon', () => {
2+
3+
it('doesn\'t exist', () => {
4+
expect(defaultPokemon).to.be.defined;
5+
});
6+
7+
it('should be a list of three pokemon', () => {
8+
expect(defaultPokemon).to.have.length(3);
9+
expect(defaultPokemon[0].name).to.be('Luvdisc')
10+
});
11+
12+
});

tutorial/06/06.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
describe('06 stores initial state', () => {
2+
3+
it('should be declared', () => {
4+
expect(store.getState()).to.be.defined;
5+
});
6+
7+
});

tutorial/06/07.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
describe('06 "pokemon" reducer', () => {
2+
3+
it('should have a default state of "defaultPokemon"', () => {
4+
expect(pokemon(null, { type: 'ANY' })).to.have.length(3);
5+
});
6+
7+
});

tutorial/06/08.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('07 "pokemon" reducer', () => {
2+
3+
it('should no longer call "state"', () => {
4+
const regex = /state/;
5+
const string = pokemon.toString();
6+
expect(string).not.to.match(regex);
7+
});
8+
9+
it('should return the correct state', () => {
10+
expect(pokemon(null, { type: 'VOTE_UP', payload: { id: 2} })[1].votes).be(1);
11+
});
12+
13+
});

tutorial/06/index.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
11
## Combine Reducers
2-
Using thunks for async actions.
2+
Create modular, composable reducers.
3+
4+
35

46
+ import `combineReducers` from redux
57
@test('06/01')
8+
@hint('Try this: `import { combineReducers } from 'redux';`')
69

7-
+ set reducers using combineReducers, pass it into store
10+
+ create a new `const reducers` and set it to "reducer". Pass "reducers" into your store for now, instead of "reducer". We'll use combineReducers shortly, but let's not break the app yet.
811
@test('06/02')
912

10-
+ create a "defaultPokemon" state
13+
+ We're going to create more than one reducer. They can't all be called "reducer", so rename your reducer "pokemon".
1114
@test('06/03')
1215

13-
+ pass the default state into the pokemon reducer
16+
+ combineReducers(), and pass in your reducer ({ pokemon })
1417
@test('06/04')
1518

16-
+ set the initial state to an empty object
19+
+ create a "defaultPokemon" state
1720
@test('06/05')
21+
22+
+ set the initial state of the store to an empty object
23+
@test('06/06')
24+
25+
+ pass the default state into the pokemon reducer
26+
@test('06/07')
27+
28+
+ We no longer pass the entire "state" inside of our reducers, only the slice of our state the reducer needs to know. Rename all references to "state" inside of your "pokemon" reducer to what it really is now: "pokemon".
29+
@test('06/08')
30+
31+
@onPageComplete('The state remains the same as before, but now ')

tutorial/tutorial.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
A [CodeRoad](https://coderoad.github.io) tutorial for learning Redux.
44

5-
@import('01')
6-
@import('02')
7-
@import('03')
8-
@import('04')
9-
@import('05')
10-
<!-- @import('06') -->
5+
<!-- @import('01') -->
6+
<!-- @import('02') -->
7+
<!-- @import('03') -->
8+
<!-- @import('04') -->
9+
<!-- @import('05') -->
10+
@import('06')
1111
<!-- @import('07') -->
1212
<!-- @import('08') -->
1313
<!-- @import('09') -->

0 commit comments

Comments
 (0)