diff --git a/index.android.js b/index.android.js index ad75f2c..cb5d3ae 100755 --- a/index.android.js +++ b/index.android.js @@ -14,10 +14,10 @@ import AppViewContainer from './src/modules/AppViewContainer' class DailyDrip extends Component { componentWillMount() { // Load existing store state from async storage - console.log('loading storage') - storageLoader(store) - .then((newState) => console.log('Loaded state:', newState)) - .catch((e) => console.log('Failed to load previous state', e)) + // console.log('loading storage') + // storageLoader(store) + // .then((newState) => console.log('Loaded state:', newState)) + // .catch((e) => console.log('Failed to load previous state', e)) } render() { diff --git a/src/actions/index.js b/src/actions/index.js index be49e65..3413cf9 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,22 +1,39 @@ export const FETCH_TOPICS = 'FETCH_TOPICS' export const FETCH_DRIPS = 'FETCH_DRIPS' +export const SET_TOPICS = 'SET_TOPICS' +export const SET_DRIPS = 'SET_DRIPS' export const SELECT_TOPIC = 'SELECT_TOPIC' +export const NO_OP = 'NO_OP' const setTopics = (topics) => { return { - type: FETCH_TOPICS, + type: SET_TOPICS, topics, } } const setDrips = (topicId, drips) => { return { - type: FETCH_DRIPS, + type: SET_DRIPS, topicId, drips, } } +const fetchTopics = () => { + return { + type: FETCH_TOPICS + } +} + +const fetchDrips = (topicId) => { + return { + type: FETCH_DRIPS, + topicId + } +} + + const selectTopic = (topicId) => { return { type: SELECT_TOPIC, @@ -24,10 +41,16 @@ const selectTopic = (topicId) => { } } -const Actions = { +const noOp = () => { + return { + type: NO_OP + } +} + +export const Actions = { setTopics, setDrips, selectTopic, + fetchTopics, + fetchDrips } - -export default Actions diff --git a/src/components/Drawer/DrawerContainer.js b/src/components/Drawer/DrawerContainer.js index cafd16f..786069b 100644 --- a/src/components/Drawer/DrawerContainer.js +++ b/src/components/Drawer/DrawerContainer.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux' -import Actions from '../../actions' +import { Actions } from '../../actions' import Drawer from '../Drawer' const mapStateToProps = (state) => { diff --git a/src/modules/AppView.android.js b/src/modules/AppView.android.js index f2cdf80..b867425 100644 --- a/src/modules/AppView.android.js +++ b/src/modules/AppView.android.js @@ -58,9 +58,10 @@ class App extends Component { } checkAuth(navigate) { + let { fetchTopics } = this.props AsyncStorage.getItem('auth_token').then((value) => { if (value) { - this.props.fetchTopics() + fetchTopics() } else { if (navigate) { navigate.to('login') diff --git a/src/modules/AppViewContainer.js b/src/modules/AppViewContainer.js index 9f12bff..489d27c 100644 --- a/src/modules/AppViewContainer.js +++ b/src/modules/AppViewContainer.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux' import AppView from './AppView' import Immutable from 'immutable' -import Actions from '../actions' +import { Actions } from '../actions' import API from '../api' export default connect( @@ -9,15 +9,8 @@ export default connect( dispatch => { return { fetchTopics: () => { - API.getTopics().then((response) => { - const topicsMap = response.data.topics.reduce((acc, topic) => { - return acc.set(topic.id, Immutable.fromJS(topic)) - }, Immutable.Map()) - dispatch(Actions.setTopics(topicsMap)) - }).catch((error) => { - console.log(error) - }) - }, + dispatch(Actions.fetchTopics()) + } } } )(AppView) diff --git a/src/scenes/Login/LoginContainer.js b/src/scenes/Login/LoginContainer.js index 9974cb4..575ca52 100644 --- a/src/scenes/Login/LoginContainer.js +++ b/src/scenes/Login/LoginContainer.js @@ -1,7 +1,7 @@ import Login from './index' import { connect } from 'react-redux' import API from '../../api' -import Actions from '../../actions' +import { Actions } from '../../actions' const mapStateToProps = () => { return {} diff --git a/src/scenes/Topic/TopicContainer.js b/src/scenes/Topic/TopicContainer.js index 66a00d5..b2ea69e 100644 --- a/src/scenes/Topic/TopicContainer.js +++ b/src/scenes/Topic/TopicContainer.js @@ -1,7 +1,6 @@ import Topic from './index' import { connect } from 'react-redux' -import API from '../../api' -import Actions from '../../actions' +import { Actions } from '../../actions' import Immutable from 'immutable' const mapStateToProps = (state) => { @@ -17,14 +16,7 @@ const mapStateToProps = (state) => { const mapDispatchToProps = (dispatch) => { return { fetchDrips: (topicId) => { - API.getDrips(topicId).then((response) => { - const dripsMap = response.data.drips.reduce((acc, drip) => { - return acc.set(drip.id, Immutable.fromJS(drip)) - }, Immutable.Map()) - dispatch(Actions.setDrips(topicId, dripsMap)) - }).catch((error) => { - console.log(error) - }) + dispatch(Actions.fetchDrips(topicId)) }, } } diff --git a/src/scenes/Topics/TopicsContainer.js b/src/scenes/Topics/TopicsContainer.js index 7b95b83..f422a9a 100644 --- a/src/scenes/Topics/TopicsContainer.js +++ b/src/scenes/Topics/TopicsContainer.js @@ -1,6 +1,6 @@ import { connect } from 'react-redux' import Topics from './index' -import Actions from '../../actions' +import { Actions } from '../../actions' const mapStateToProps = (state) => { const topics = state.get('topics') diff --git a/src/store/index.js b/src/store/index.js index 11fd760..7848f42 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,5 +1,5 @@ import { createStore, applyMiddleware, compose } from 'redux' -import { combineReducers } from 'redux-immutablejs' +//import { combineReducers } from 'redux-immutablejs' import * as storage from 'redux-storage' import createEngine from 'redux-storage-engine-reactnativeasyncstorage' import merger from 'redux-storage-merger-immutablejs' @@ -19,17 +19,17 @@ import Immutable from 'immutable' import * as reducers from './reducers' // LOG OUT STATE CHANGES -// import createLogger from 'redux-logger' -// const loggerMiddleware = createLogger({ -// stateTransformer: state => state && state.toJS(), -// }) +import createLogger from 'redux-logger' +const loggerMiddleware = createLogger({ + stateTransformer: state => state && state.toJS(), +}) // END LOG OUT STATE CHANGES // STORE REDUX STATE -const reducer = storage.reducer(combineReducers(reducers), merger) -const storageEngine = createEngine('@DAILYDRIP.reduxStore') -const storageMiddleware = storage.createMiddleware(storageEngine) -export const storageLoader = storage.createLoader(storageEngine) +// const reducer = storage.reducer(combineReducers(reducers), merger) +// const storageEngine = createEngine('@DAILYDRIP.reduxStore') +// const storageMiddleware = storage.createMiddleware(storageEngine) +// export const storageLoader = storage.createLoader(storageEngine) // END STORE REDUX STATE const initialState = Immutable.fromJS({ @@ -37,14 +37,26 @@ const initialState = Immutable.fromJS({ selectedTopic: {}, // NOTE: This is presently intended to end up as just a map with a basic `id` key - this is because you can't do immutable ints and I wanted to use createReducer throughout, but it's probably dumb... }) +console.log('initialState', initialState) + const enhancer = compose( - // applyMiddleware(loggerMiddleware, storageMiddleware), - applyMiddleware(storageMiddleware), + //applyMiddleware(loggerMiddleware, storageMiddleware), + applyMiddleware(loggerMiddleware), Loop.install(), - devTools() + devTools(), +) + +const store = createStore( + Loop.combineReducers( + reducers, + Immutable.Map(), + (state, key) => state.get(key), + (state, key, value) => state.set(key, value) + ), + initialState, + enhancer ) -const store = createStore(reducer, initialState, enhancer) devTools.updateStore(store) export default store diff --git a/src/store/reducers/topics.js b/src/store/reducers/topics.js index a573bcd..b42e247 100644 --- a/src/store/reducers/topics.js +++ b/src/store/reducers/topics.js @@ -1,24 +1,87 @@ -import { createReducer } from 'redux-immutablejs' import Immutable from 'immutable' -import { FETCH_TOPICS, FETCH_DRIPS } from '../../actions' - -export default createReducer(Immutable.Map(), { - [FETCH_TOPICS]: (state, action) => { - return action.topics.map((topic) => { - // Look in the store and pull in any drips we already know about, since - // we don't have them here but we'd like to keep them for faster startup - // from storage - const existingTopic = state.get(topic.get('id').toString()) - let newTopic - if (existingTopic) { - newTopic = topic.set('drips', existingTopic.get('drips')) - } else { - newTopic = topic - } - return newTopic +import { Actions, SET_TOPICS, SET_DRIPS, FETCH_TOPICS, FETCH_DRIPS } from '../../actions' +import { loop, Effects } from 'redux-loop'; +import API from '../../api' + + +let fetchTopics = () => ( + API.getTopics() + .then((response) => { + return Actions.setTopics( + response.data.topics + .reduce((acc, topic) => { + return acc + .set(topic.id, Immutable.fromJS(topic)) + }, Immutable.Map()) + ) + }) + .catch((err) => { + console.error(err) + return Actions.noOp() }) - }, - [FETCH_DRIPS]: (state, { topicId, drips }) => { - return state.setIn([topicId, 'drips'], drips) - }, -}) +) + +let fetchDrips = (topicId) => { + return API.getDrips(topicId) + .then((response) => { + return Actions.setDrips( + topicId, + response.data.drips + .reduce((acc, drip) => ( + acc.set(drip.id, Immutable.fromJS(drip)) + ), Immutable.Map()) + )}) + .catch((err) => { + console.error(err) + return Actions.noOp() + }) +} + +export default function(state, action){ + switch (action.type) { + case FETCH_TOPICS: + return loop( + state, + Effects.promise(fetchTopics) + ) + + case SET_TOPICS: + const topics = action.topics.map((topic) => { + // Look in the store and pull in any drips we already know about, since + // we don't have them here but we'd like to keep them for faster startup + // from storage + const existingTopic = state.get(topic.get('id').toString()) + let newTopic + if (existingTopic) { + newTopic = topic.set('drips', existingTopic.get('drips')) + } else { + newTopic = topic + } + return newTopic + }) + + return loop( + topics, + Effects.none() + ) + + case FETCH_DRIPS: + return loop( + state, + Effects.promise(fetchDrips, action.topicId) + ) + + case SET_DRIPS: + return loop( + state + .setIn([action.topicId, 'drips'], action.drips), + Effects.none() + ) + + default: + return loop( + state, + Effects.none() + ) + } +}