Add basic redux setup
This commit is contained in:
parent
eccbdf4a79
commit
fbbc8bd814
9 changed files with 142 additions and 18 deletions
29
app/actions/buildAsyncAction.js
Normal file
29
app/actions/buildAsyncAction.js
Normal 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
16
app/actions/index.js
Normal 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 }
|
||||||
|
);
|
||||||
|
}
|
7
app/actions/makeAsyncActionSet.js
Normal file
7
app/actions/makeAsyncActionSet.js
Normal 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
6
app/actions/methods.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export default {
|
||||||
|
GET: 'GET',
|
||||||
|
PATCH: 'PATCH',
|
||||||
|
POST: 'POST',
|
||||||
|
PUT: 'PUT'
|
||||||
|
};
|
43
app/index.js
43
app/index.js
|
@ -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
9
app/reducers/index.js
Normal 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
11
app/reducers/user.js
Normal 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
35
app/store.js
Normal 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;
|
||||||
|
}
|
|
@ -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"
|
||||||
|
|
Reference in a new issue