Loading user feed using redux-saga

This commit is contained in:
Bruno Lemos
2016-11-27 05:50:24 -02:00
parent 9b54a10465
commit 08a896364c
12 changed files with 105 additions and 74 deletions

View File

@@ -4,8 +4,6 @@ import android.app.Application;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.rnfs.RNFSPackage;
import com.rnfs.RNFSPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.reactnativenavigation.NavigationReactPackage;
import com.oblador.vectoricons.VectorIconsPackage;
@@ -31,8 +29,6 @@ public class MainApplication extends Application implements ReactApplication {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNFSPackage(),
new RNFSPackage(),
new LinearGradientPackage(),
new NavigationReactPackage(),
new VectorIconsPackage(),

View File

@@ -3,11 +3,22 @@
import {
SET_THEME,
LOAD_FEED_REQUEST,
LOAD_USER_FEED_REQUEST,
LOAD_USER_FEED_SUCCESS,
LOAD_USER_FEED_FAILURE,
} from '../utils/constants/actions';
import { action } from '../utils/helpers/actions';
import { action, errorAction } from '../utils/helpers/actions';
import type { Theme } from '../utils/types';
export const setTheme = (theme: Theme) => action(SET_THEME, theme);
export const loadFeedRequest = () => action(LOAD_FEED_REQUEST);
export const loadUserFeedRequest = (username: string) => (
action(LOAD_USER_FEED_REQUEST, { username })
);
export const loadUserFeedSuccess = (username: string, data: any, meta: Object) => (
action(LOAD_USER_FEED_SUCCESS, { username, data, meta })
);
export const loadUserFeedFailure = (error: any) => errorAction(LOAD_USER_FEED_FAILURE, error);

3
src/api/github.js Normal file
View File

@@ -0,0 +1,3 @@
import GitHubAPI from 'github';
export default new GitHubAPI();

View File

@@ -19,12 +19,8 @@ export default class extends React.Component {
theme: this.props.theme || this.context.theme,
});
children: {
theme: ThemeObject,
};
props: {
children: React.Element<*>,
children?: ?React.Element<*>,
theme: ThemeObject,
};

View File

@@ -6,21 +6,34 @@ import { connect } from 'react-redux';
import Columns from '../components/Columns';
import Screen from '../components/Screen';
import ThemeProvider from '../components/ThemeProvider';
import { loadUserFeedRequest } from '../actions';
import { loadTheme } from '../reducers/config';
import type { State, ThemeObject } from '../utils/types';
type Props = State & {
theme: ThemeObject,
};
class Page extends React.Component {
componentDidMount() {
this.props.loadUserFeedRequest('brunolemos');
}
const Page = ({ feed, theme }: Props) => (
<ThemeProvider theme={theme}>
<Screen>
<Columns columns={feed} />
</Screen>
</ThemeProvider>
);
props: State & {
theme: ThemeObject,
loadUserFeedRequest: Function,
};
render() {
const { feed, theme } = this.props;
return (
<ThemeProvider theme={theme}>
<Screen>
<Columns columns={feed} />
</Screen>
</ThemeProvider>
);
}
}
const mapStateToProps = ({ feed, config }: State) => ({ feed, theme: loadTheme(config) });
const mapDispatchToProps = { loadUserFeedRequest };
export default connect(mapStateToProps)(Page);
export default connect(mapStateToProps, mapDispatchToProps)(Page);

View File

@@ -17,16 +17,3 @@ export default () => (
</NavigationProvider>
</Provider>
);
// import GitHubAPI from 'github';
//
// const github = new GitHubAPI();
//
// (async () => {
// try {
// const result = await github.activity.getEventsReceived({ username: 'brunolemos' });
// console.log(result);
// } catch(e) {
// console.log('Error', e);
// }
// })();

View File

@@ -2,29 +2,34 @@
import { combineReducers } from 'redux';
import { LOAD_FEED_SUCCESS } from '../utils/constants/actions';
import { LOAD_USER_FEED_SUCCESS } from '../utils/constants/actions';
import type { Action } from '../utils/types';
import type { GithubEvent } from '../utils/types/github';
// static data
import allEventsData from '../../test/data/github-bigquery.json';
import repoEventsData from '../../test/data/github-repo-events.json';
import userEventsData from '../../test/data/github-user-events.json';
import userReceivedEventsData from '../../test/data/github-user-received_events.json';
// // static data
// import allEventsData from '../../test/data/github-bigquery.json';
// import repoEventsData from '../../test/data/github-repo-events.json';
// import userEventsData from '../../test/data/github-user-events.json';
// import userReceivedEventsData from '../../test/data/github-user-received_events.json';
//
// const data = [
// { id: 0, title: 'all', data: allEventsData },
// { id: 1, title: 'react', data: repoEventsData },
// { id: 2, title: 'sibelius', data: userReceivedEventsData },
// { id: 3, title: 'brunolemos', data: userEventsData },
// ];
const data = [
{ id: 0, title: 'all', data: allEventsData },
{ id: 1, title: 'react', data: repoEventsData },
{ id: 2, title: 'sibelius', data: userReceivedEventsData },
{ id: 3, title: 'brunolemos', data: userEventsData },
];
type Column = { id: string, title: string, data: Array<GithubEvent>, meta: Object };
type LoadUserFeedPayload = { username: string, data: Array<GithubEvent> };
export default (state :Array<Column> = [], action: Action<LoadUserFeedPayload>): Array<Column> => {
const { type, payload: { username, data } = {} } = action || {};
export default (state:Array<GithubEvent> = data, { type, payload }: Action<Array<GithubEvent>>): Array<GithubEvent> => {
switch (type) {
case LOAD_FEED_SUCCESS: return [
...payload,
...state,
];
case LOAD_USER_FEED_SUCCESS: return [{
id: '0',
title: username,
data,
}];
default: return state;
}
};

View File

@@ -1,24 +1,33 @@
// @flow
import { put, takeEvery } from 'redux-saga';
import { takeEvery } from 'redux-saga';
import { call, put } from 'redux-saga/effects';
import { LOAD_USER_FEED_REQUEST } from '../utils/constants/actions';
import {
LOAD_FEED_REQUEST,
} from '../utils/constants/actions';
loadUserFeedSuccess,
loadUserFeedFailure,
} from '../actions';
import { loadFeedRequest } from '../actions';
import github from '../api/github';
export function* loadFeed(): Generator<*, *, *> {
yield put(loadFeedRequest())
export function* loadUserFeed({ payload: { username } = {} }: Object): Generator<*, *, *> {
try {
const { data, meta } = yield call(github.activity.getEventsReceived, { username });
yield put(loadUserFeedSuccess(username, data, meta))
} catch (error) {
yield put(loadUserFeedFailure(error))
}
}
// Our watcher Saga: spawn a new incrementAsync task on each INCREMENT_ASYNC
export function* watchLoadFeed(): Generator<*, *, *> {
yield takeEvery(LOAD_FEED_REQUEST, loadFeed)
export function* watchloadUserFeed(): Generator<*, *, *> {
yield takeEvery(LOAD_USER_FEED_REQUEST, loadUserFeed)
}
export default function* (): Generator<*, *, *> {
return yield [
watchLoadFeed
watchloadUserFeed()
];
}

View File

@@ -26,7 +26,6 @@ const store = createStoreWithNavigation(
sagaMiddleware.run(sagas);
// TODO: Don't ignore feed
persistStore(store, { storage: AsyncStorage, whitelist: ['config'] });
persistStore(store, { storage: AsyncStorage, blacklist: ['navigation'] });
export default store;

View File

@@ -2,6 +2,6 @@
/* eslint-disable import/prefer-default-export */
export const SET_THEME = 'SET_THEME';
export const LOAD_FEED_REQUEST = 'LOAD_FEED_REQUEST';
export const LOAD_FEED_SUCCESS = 'LOAD_FEED_SUCCESS';
export const LOAD_FEED_FAILURE = 'LOAD_FEED_FAILURE';
export const LOAD_USER_FEED_REQUEST = 'LOAD_USER_FEED_REQUEST';
export const LOAD_USER_FEED_SUCCESS = 'LOAD_USER_FEED_SUCCESS';
export const LOAD_USER_FEED_FAILURE = 'LOAD_USER_FEED_FAILURE';

View File

@@ -3,7 +3,7 @@
import type { ActionType } from '../types';
/**
* Create the action object
* Create an action object
*
* Example:
* action('LOGIN_REQUEST', { email, password })
@@ -13,3 +13,15 @@ import type { ActionType } from '../types';
export function action(type: ActionType, payload: any) {
return { type, payload };
}
/**
* Create an action error object
*
* Example:
* errorAction('LOGIN_FAILURE', { message: 'No internet connection' })
* produces
* { type: 'LOGIN_FAILURE', error: { message: '...' } }
*/
export function errorAction(type: ActionType, error: any) {
return { type, error };
}

View File

@@ -4,15 +4,15 @@
*/
export type SET_THEME = 'SET_THEME';
export type LOAD_FEED_REQUEST = 'LOAD_FEED_REQUEST';
export type LOAD_FEED_SUCCESS = 'LOAD_FEED_SUCCESS';
export type LOAD_FEED_FAILURE = 'LOAD_FEED_FAILURE';
export type LOAD_USER_FEED_REQUEST = 'LOAD_USER_FEED_REQUEST';
export type LOAD_USER_FEED_SUCCESS = 'LOAD_USER_FEED_SUCCESS';
export type LOAD_USER_FEED_FAILURE = 'LOAD_USER_FEED_FAILURE';
export type ActionType =
| SET_THEME
| LOAD_FEED_REQUEST
| LOAD_FEED_SUCCESS
| LOAD_FEED_FAILURE;
| LOAD_USER_FEED_REQUEST
| LOAD_USER_FEED_SUCCESS
| LOAD_USER_FEED_FAILURE;
export type Action<T> = {
type: ActionType,