Skip to content

Commit 94efe05

Browse files
committed
part 14
1 parent 779d52f commit 94efe05

File tree

10 files changed

+138
-20
lines changed

10 files changed

+138
-20
lines changed

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"react-redux": "^5.0.5",
99
"react-scripts": "1.0.10",
1010
"redux": "^3.7.2",
11-
"redux-logger": "^3.0.6"
11+
"redux-logger": "^3.0.6",
12+
"redux-saga": "^0.15.6"
1213
},
1314
"scripts": {
1415
"start": "react-scripts start",

src/actions/story.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {
2+
STORIES_ADD,
3+
STORIES_FETCH,
4+
} from '../constants/actionTypes';
5+
6+
const doAddStories = stories => ({
7+
type: STORIES_ADD,
8+
stories,
9+
});
10+
11+
const doFetchStories = query => ({
12+
type: STORIES_FETCH,
13+
query,
14+
});
15+
16+
export {
17+
doAddStories,
18+
doFetchStories,
19+
};

src/components/App.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ import React from 'react';
22
import './App.css';
33

44
import Stories from './Stories';
5+
import SearchStories from './SearchStories';
56

67
const App = () =>
78
<div className="app">
9+
<div className="interactions">
10+
<SearchStories />
11+
</div>
812
<Stories />
913
</div>
1014

src/components/SearchStories.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React, { Component } from 'react';
2+
import { connect } from 'react-redux';
3+
import { doFetchStories } from '../actions/story';
4+
import Button from './Button';
5+
6+
const applyQueryState = query => () => ({
7+
query
8+
});
9+
10+
class SearchStories extends Component {
11+
constructor(props) {
12+
super(props);
13+
14+
this.state = {
15+
query: '',
16+
};
17+
18+
this.onChange = this.onChange.bind(this);
19+
this.onSubmit = this.onSubmit.bind(this);
20+
}
21+
22+
onSubmit(event) {
23+
const { query } = this.state;
24+
if (query) {
25+
this.props.onFetchStories(query)
26+
27+
this.setState(applyQueryState(''));
28+
}
29+
30+
event.preventDefault();
31+
}
32+
33+
onChange(event) {
34+
const { value } = event.target;
35+
this.setState(applyQueryState(value));
36+
}
37+
38+
render() {
39+
return (
40+
<form onSubmit={this.onSubmit}>
41+
<input
42+
type="text"
43+
value={this.state.query}
44+
onChange={this.onChange}
45+
/>
46+
<Button type="submit">
47+
Search
48+
</Button>
49+
</form>
50+
);
51+
}
52+
}
53+
54+
const mapDispatchToProps = (dispatch) => ({
55+
onFetchStories: query => dispatch(doFetchStories(query)),
56+
});
57+
58+
export default connect(
59+
null,
60+
mapDispatchToProps
61+
)(SearchStories);

src/constants/actionTypes.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
export const STORY_ARCHIVE = 'STORY_ARCHIVE';
1+
export const STORY_ARCHIVE = 'STORY_ARCHIVE';
2+
export const STORIES_FETCH = 'STORIES_FETCH';
3+
export const STORIES_ADD = 'STORIES_ADD';

src/reducers/story.js

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,15 @@
1-
const INITIAL_STATE = [
2-
{
3-
title: 'React',
4-
url: 'https://facebook.github.io/react/',
5-
author: 'Jordan Walke',
6-
num_comments: 3,
7-
points: 4,
8-
objectID: 0,
9-
}, {
10-
title: 'Redux',
11-
url: 'https://github.com/reactjs/redux',
12-
author: 'Dan Abramov, Andrew Clark',
13-
num_comments: 2,
14-
points: 5,
15-
objectID: 1,
16-
},
17-
];
1+
import { STORIES_ADD } from '../constants/actionTypes';
2+
3+
const INITIAL_STATE = [];
4+
5+
const applyAddStories = (state, action) =>
6+
action.stories;
187

198
function storyReducer(state = INITIAL_STATE, action) {
209
switch(action.type) {
10+
case STORIES_ADD : {
11+
return applyAddStories(state, action);
12+
}
2113
default : return state;
2214
}
2315
}

src/sagas/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { takeEvery, all } from 'redux-saga/effects';
2+
import { STORIES_FETCH } from '../constants/actionTypes';
3+
import { handleFetchStories } from './story';
4+
5+
function *watchAll() {
6+
yield all([
7+
takeEvery(STORIES_FETCH, handleFetchStories),
8+
])
9+
}
10+
11+
export default watchAll;

src/sagas/story.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { call, put } from 'redux-saga/effects';
2+
import { doAddStories } from '../actions/story';
3+
4+
const HN_BASE_URL = 'http://hn.algolia.com/api/v1/search?query=';
5+
6+
const fetchStories = query =>
7+
fetch(HN_BASE_URL + query)
8+
.then(response => response.json());
9+
10+
function* handleFetchStories(action) {
11+
const { query } = action;
12+
const result = yield call(fetchStories, query);
13+
yield put(doAddStories(result.hits));
14+
}
15+
16+
export {
17+
handleFetchStories,
18+
};

src/store/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
import { createStore, applyMiddleware } from 'redux';
22
import { createLogger } from 'redux-logger';
3+
import createSagaMiddleware from 'redux-saga';
34
import rootReducer from '../reducers';
5+
import rootSaga from '../sagas';
46

57
const logger = createLogger();
8+
const saga = createSagaMiddleware();
69

710
const store = createStore(
811
rootReducer,
912
undefined,
10-
applyMiddleware(logger)
13+
applyMiddleware(saga, logger)
1114
);
1215

16+
saga.run(rootSaga);
17+
1318
export default store;

0 commit comments

Comments
 (0)