Last active
January 19, 2017 21:02
-
-
Save kamilglod/972bf23c0bb9d5a33a0802f359b78e11 to your computer and use it in GitHub Desktop.
Aurelia redux sync, updates aurelia's viewModel each time the change of state occured. Aurelia, Redux, ImmutableJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { getHttp } from 'utils/fetch'; | |
import { HISTORY_URL } from 'conf/urls'; | |
const types = { | |
START_FETCHING_HISTORY: 'START_FETCHING_HISTORY', | |
FINISH_FETCHING_HISTORY: 'FINISH_FETCHING_HISTORY', | |
INVALIDATE_HISTORY: 'INVALIDATE_HISTORY', | |
}; | |
function _startFetchingHistory() { | |
return { | |
type: types.START_FETCHING_HISTORY, | |
}; | |
} | |
function _finishFetchingHistory(data) { | |
return { | |
type: types.FINISH_FETCHING_HISTORY, | |
data, | |
}; | |
} | |
function fetchHistory(dispatch) { | |
dispatch(_startFetchingHistory()); | |
return getHttp().fetch(HISTORY_URL) | |
.then(response => response.json()) | |
.then(json => dispatch(_finishFetchingHistory(json))); | |
} | |
function _isFetchNeeded(historyState) { | |
if (historyState.get('isFetching')) { | |
return false; | |
} else if (historyState.get('didInvalidate')) { | |
return true; | |
} else { | |
return !historyState.get('fetched'); | |
} | |
} | |
function fetchHistoryIfNeeded() { | |
return (dispatch, getState) => { | |
const historyState = getState().history; | |
if (!_isFetchNeeded(historyState)) { | |
return Promise.resolve(); | |
} | |
return fetchHistory(dispatch); | |
}; | |
} | |
function invalidateHistory() { | |
return { | |
type: types.INVALIDATE_HISTORY, | |
} | |
} | |
export { types, fetchHistoryIfNeeded, fetchHistory, invalidateHistory, }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
${history.data} | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import StoreSync from 'utils/store-sync'; | |
import { fetchHistoryIfNeeded } from 'flux/actions/history'; | |
export class History { | |
constructor() { | |
this.store = StoreSync.init(this, 'history', 'auth').store; | |
this.store.dispatch(fetchHistoryIfNeeded()); | |
// you can now access states properties | |
console.log(this.history, this.auth); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { List, Map } from 'immutable'; | |
import { types } from '../actions/history'; | |
import { types as authTypes } from '../actions/auth'; | |
function getInitialState() { | |
return new Map({ | |
isFetching: false, | |
didInvalidate: false, | |
fetched: false, | |
data: new List(), | |
}); | |
} | |
export default function(state, action) { | |
if (!state) { | |
state = getInitialState(); | |
} | |
switch (action.type) { | |
case types.START_FETCHING_HISTORY: | |
state = state.set('isFetching', true); | |
break; | |
case types.FINISH_FETCHING_HISTORY: | |
state = getInitialState().set('data', action.data).set('fetched', true); | |
break; | |
case types.INVALIDATE_HISTORY: | |
state = state.set('didInvalidate', true); | |
break; | |
case authTypes.LOGGED_OUT: | |
state = getInitialState(); | |
break; | |
} | |
return state; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Container } from 'aurelia-dependency-injection'; | |
import store from 'flux/store'; | |
export default class StoreSync { | |
static init(...args) { | |
return new StoreSync(...args); | |
} | |
constructor(viewModel, ...args) { | |
this.viewModel = viewModel; | |
this.store = Container.instance.get(store); | |
this._syncStateKeys = args; | |
this._initSyncedStates(); | |
this._sync(true); | |
this._syncInvoker = this.store.subscribe(() => this._sync()); | |
} | |
detached() { | |
if (this._syncInvoker) { | |
this._syncInvoker(); | |
} | |
} | |
_fillSyncedState(state) { | |
for (const stateKey of this._syncStateKeys) { | |
this._syncedState[stateKey] = state[stateKey]; | |
} | |
} | |
_initSyncedStates() { | |
const state = this.store.getState(); | |
this._syncedState = {}; | |
this._fillSyncedState(state); | |
} | |
_isSyncNeeded() { | |
const state = this.store.getState(); | |
for (const stateKey of this._syncStateKeys) { | |
if (this._syncedState[stateKey] != state[stateKey]) { | |
return true; | |
} | |
} | |
return false; | |
} | |
_sync(force = false) { | |
const state = this.store.getState(); | |
if (!force && !this._isSyncNeeded()) { | |
return; | |
} | |
for (const stateKey of this._syncStateKeys) { | |
this.viewModel[stateKey] = state[stateKey].toJS(); | |
} | |
this._fillSyncedState(state); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createStore, applyMiddleware, compose, combineReducers } from 'redux' | |
import thunkMiddleware from 'redux-thunk' | |
import auth from './reducers/auth'; | |
import history from './reducers/history'; | |
const reducers = combineReducers({ | |
auth, | |
history, | |
}); | |
function configureStore() { | |
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; | |
return createStore( | |
reducers, | |
composeEnhancers( | |
applyMiddleware( | |
thunkMiddleware, | |
), | |
) | |
) | |
} | |
export default configureStore(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment