Add basic redux setup

This commit is contained in:
Jake Howard 2016-04-28 17:34:20 +01:00
parent eccbdf4a79
commit fbbc8bd814
9 changed files with 142 additions and 18 deletions

View file

@ -0,0 +1,29 @@
import { CALL_API } from 'redux-api-middleware';
import _ from 'underscore';
export default function buildRsaAction(actionSet, path, method, optionalData, meta) {
const types = _.map([actionSet.REQUEST, actionSet.SUCCESS, actionSet.FAILURE], (requestType) => {
if (meta) {
return { type: requestType, meta: _.clone(meta) };
}
return { type: requestType };
});
let actionData = {
types: types,
endpoint: path,
method,
headers: {
'Accept': 'application/json'
},
};
if (optionalData && !_.isEmpty(optionalData)) {
actionData.headers['Content-Type'] = 'application/json';
actionData.body = JSON.stringify(optionalData);
}
return {
[CALL_API]: actionData
};
}

16
app/actions/index.js Normal file
View file

@ -0,0 +1,16 @@
import methods from './methods';
import makeAsyncActionSet from './makeAsyncActionSet';
import buildAsyncAction from './buildAsyncAction';
import endpoints from '../settings/endpoints';
export const LOGIN = makeAsyncActionSet('LOGIN');
export function login(token) {
return buildAsyncAction(
LOGIN,
endpoints.get('USER_INFO').query({ 'circle-token': token }).toString(),
methods.GET,
{},
{ token }
);
}

View file

@ -0,0 +1,7 @@
export default function makeAsyncActionSet(actionName) {
return {
REQUEST: actionName + '_REQUEST',
SUCCESS: actionName + '_SUCCESS',
FAILURE: actionName + '_FAILURE'
};
}

6
app/actions/methods.js Normal file
View file

@ -0,0 +1,6 @@
export default {
GET: 'GET',
PATCH: 'PATCH',
POST: 'POST',
PUT: 'PUT'
};

View file

@ -5,6 +5,9 @@ import RouteMapper from './components/navigation/RouteMapper';
import GlobalStyles from './settings/styles'; import GlobalStyles from './settings/styles';
import BusyIndicator from 'react-native-busy-indicator'; import BusyIndicator from 'react-native-busy-indicator';
import { Provider } from 'react-redux';
import configureStore from './store';
require('moment-duration-format'); require('moment-duration-format');
const { const {
@ -26,7 +29,9 @@ const styles = StyleSheet.create({
} }
}); });
export default class extends React.Component { const store = configureStore();
export default class App extends React.Component {
renderScene(route, nav) { renderScene(route, nav) {
const Component = route.component; const Component = route.component;
const props = route.props || {}; const props = route.props || {};
@ -46,24 +51,26 @@ export default class extends React.Component {
render() { render() {
return ( return (
<View style={{ flex: 1 }}> <Provider store={store}>
<Navigator <View style={{ flex: 1 }}>
renderScene={this.renderScene} <Navigator
initialRoute={this.initialRoute} renderScene={this.renderScene}
navigationBar={ initialRoute={this.initialRoute}
<Navigator.NavigationBar navigationBar={
style={styles.navbar} <Navigator.NavigationBar
routeMapper={RouteMapper} /> style={styles.navbar}
} routeMapper={RouteMapper} />
configureScene={(route) => {
if (route.sceneConfig) {
return route.sceneConfig;
} }
return Navigator.SceneConfigs.PushFromRight; configureScene={(route) => {
}} if (route.sceneConfig) {
/> return route.sceneConfig;
<BusyIndicator /> }
</View> return Navigator.SceneConfigs.PushFromRight;
}}
/>
<BusyIndicator />
</View>
</Provider>
); );
} }
}; };

9
app/reducers/index.js Normal file
View file

@ -0,0 +1,9 @@
import { combineReducers } from 'redux';
import * as storage from 'redux-storage';
import user from './user';
export default storage.reducer(combineReducers({
user
}));

11
app/reducers/user.js Normal file
View file

@ -0,0 +1,11 @@
import * as actions from '../actions';
import { Map } from 'immutable';
export default function user(state = Map(), action) {
console.log(action.type);
if (action.type === actions.LOGIN.SUCCESS) {
console.log('SUCCESS!', action.meta.token);
return Map(action.payload).set('token', action.meta.token);
}
return state;
}

35
app/store.js Normal file
View file

@ -0,0 +1,35 @@
import { createStore, applyMiddleware } from 'redux';
import reducers from './reducers';
import settings from './settings/constants';
import * as storage from 'redux-storage';
import createEngine from 'redux-storage-engine-reactnativeasyncstorage';
import filter from 'redux-storage-decorator-filter';
import { apiMiddleware } from 'redux-api-middleware';
const engine = filter(createEngine(settings.get('STORAGE_KEY')));
const storeMiddleware = storage.createMiddleware(engine);
export default function configureStore(initialState) {
const load = storage.createLoader(engine);
const createStoreWithMiddleware = applyMiddleware(
apiMiddleware,
storeMiddleware // Last in list
)(createStore);
const store = createStoreWithMiddleware(reducers);
load(store)
.then(function (newData) {
console.log('LOADED STATE');
})
.catch(function () {
console.log('FAILED TO LOAD STATE', arguments);
});
return store;
}

View file

@ -22,6 +22,10 @@
"react-redux": "=3.1.2", "react-redux": "=3.1.2",
"redux": "=3.0.5", "redux": "=3.0.5",
"redux-api-middleware": "git://github.com/realorangeone/redux-api-middleware#4edf49b04fe459cc69c8ccd758180d3a6d66bf2e", "redux-api-middleware": "git://github.com/realorangeone/redux-api-middleware#4edf49b04fe459cc69c8ccd758180d3a6d66bf2e",
"redux-storage": "=4.0.0",
"redux-storage-decorator-filter": "=1.1.3",
"redux-storage-engine-reactnativeasyncstorage": "=1.0.0",
"redux-storage-merger-immutablejs": "=1.0.1",
"underscore": "=1.8.3", "underscore": "=1.8.3",
"url": "=0.11.0", "url": "=0.11.0",
"url-assembler": "=1.2.4" "url-assembler": "=1.2.4"