From fbbc8bd814c59d01bdcbde0b2321c361bca2cd13 Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Thu, 28 Apr 2016 17:34:20 +0100 Subject: [PATCH] Add basic redux setup --- app/actions/buildAsyncAction.js | 29 +++++++++++++++++++++ app/actions/index.js | 16 ++++++++++++ app/actions/makeAsyncActionSet.js | 7 +++++ app/actions/methods.js | 6 +++++ app/index.js | 43 ++++++++++++++++++------------- app/reducers/index.js | 9 +++++++ app/reducers/user.js | 11 ++++++++ app/store.js | 35 +++++++++++++++++++++++++ package.json | 4 +++ 9 files changed, 142 insertions(+), 18 deletions(-) create mode 100644 app/actions/buildAsyncAction.js create mode 100644 app/actions/index.js create mode 100644 app/actions/makeAsyncActionSet.js create mode 100644 app/actions/methods.js create mode 100644 app/reducers/index.js create mode 100644 app/reducers/user.js create mode 100644 app/store.js diff --git a/app/actions/buildAsyncAction.js b/app/actions/buildAsyncAction.js new file mode 100644 index 0000000..d0d9b2a --- /dev/null +++ b/app/actions/buildAsyncAction.js @@ -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 + }; +} diff --git a/app/actions/index.js b/app/actions/index.js new file mode 100644 index 0000000..e391e96 --- /dev/null +++ b/app/actions/index.js @@ -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 } + ); +} diff --git a/app/actions/makeAsyncActionSet.js b/app/actions/makeAsyncActionSet.js new file mode 100644 index 0000000..b81e3f7 --- /dev/null +++ b/app/actions/makeAsyncActionSet.js @@ -0,0 +1,7 @@ +export default function makeAsyncActionSet(actionName) { + return { + REQUEST: actionName + '_REQUEST', + SUCCESS: actionName + '_SUCCESS', + FAILURE: actionName + '_FAILURE' + }; +} diff --git a/app/actions/methods.js b/app/actions/methods.js new file mode 100644 index 0000000..b542530 --- /dev/null +++ b/app/actions/methods.js @@ -0,0 +1,6 @@ +export default { + GET: 'GET', + PATCH: 'PATCH', + POST: 'POST', + PUT: 'PUT' +}; diff --git a/app/index.js b/app/index.js index 3e6bbf6..0a2fab4 100644 --- a/app/index.js +++ b/app/index.js @@ -5,6 +5,9 @@ import RouteMapper from './components/navigation/RouteMapper'; import GlobalStyles from './settings/styles'; import BusyIndicator from 'react-native-busy-indicator'; +import { Provider } from 'react-redux'; +import configureStore from './store'; + require('moment-duration-format'); 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) { const Component = route.component; const props = route.props || {}; @@ -46,24 +51,26 @@ export default class extends React.Component { render() { return ( - - - } - configureScene={(route) => { - if (route.sceneConfig) { - return route.sceneConfig; + + + } - return Navigator.SceneConfigs.PushFromRight; - }} - /> - - + configureScene={(route) => { + if (route.sceneConfig) { + return route.sceneConfig; + } + return Navigator.SceneConfigs.PushFromRight; + }} + /> + + + ); } }; diff --git a/app/reducers/index.js b/app/reducers/index.js new file mode 100644 index 0000000..79943c3 --- /dev/null +++ b/app/reducers/index.js @@ -0,0 +1,9 @@ +import { combineReducers } from 'redux'; +import * as storage from 'redux-storage'; + +import user from './user'; + + +export default storage.reducer(combineReducers({ + user +})); diff --git a/app/reducers/user.js b/app/reducers/user.js new file mode 100644 index 0000000..f48a65d --- /dev/null +++ b/app/reducers/user.js @@ -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; +} diff --git a/app/store.js b/app/store.js new file mode 100644 index 0000000..830b0cf --- /dev/null +++ b/app/store.js @@ -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; +} diff --git a/package.json b/package.json index f7ac3b7..4efe5ab 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,10 @@ "react-redux": "=3.1.2", "redux": "=3.0.5", "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", "url": "=0.11.0", "url-assembler": "=1.2.4"