Last active
November 22, 2018 13:11
-
-
Save thehig/08a1bcabab38f0a0bf063280ee679ef1 to your computer and use it in GitHub Desktop.
js: ReduxInjector
This file contains hidden or 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
/** | |
* Created by guillaume on 1/17/17. | |
*/ | |
import { createInjectStore } from 'redux-reducers-injector'; | |
import createSagaMiddleware from 'redux-saga'; | |
import { take, fork, cancel } from 'redux-saga/effects'; | |
export const CANCEL_SAGAS_HMR = 'CANCEL_SAGAS_HMR'; | |
let original_store = {}; | |
function createAbortableSaga(key, saga, store = original_store) { | |
console.log('createAbortableSaga', key, saga, store); | |
if (process.env.NODE_ENV === 'development') { | |
return function* main() { | |
const sagaTask = yield fork(saga); | |
const { payload } = yield take(CANCEL_SAGAS_HMR); | |
if (payload === key) { | |
yield cancel(sagaTask, store); | |
} | |
}; | |
} else { | |
return saga; | |
} | |
} | |
export const SagaManager = { | |
startSaga(key, saga, store = original_store) { | |
console.log('startSaga', key, saga, store); | |
sagaMiddleware.run(createAbortableSaga(key, saga, store)); | |
}, | |
cancelSaga(key, store = original_store) { | |
console.log('cancelSaga', key, store); | |
store.dispatch({ | |
type: CANCEL_SAGAS_HMR, | |
payload: key | |
}); | |
} | |
}; | |
export function reloadSaga(key, saga, store = original_store) { | |
console.log('reloadSaga', key, saga, store); | |
SagaManager.cancelSaga(key, store); | |
SagaManager.startSaga(key, saga, store); | |
} | |
export function injectSaga(key, saga, force = false, store = original_store) { | |
console.log('injectSaga', key, saga, force, store); | |
// If already set, do nothing, except force is specified | |
const exists = store.injectedSagas.includes(key); | |
if (!exists || force) { | |
if (!exists) { | |
store.injectedSagas = [...store.injectedSagas, key]; | |
} | |
if (force) { | |
SagaManager.cancelSaga(key, store); | |
} | |
SagaManager.startSaga(key, saga, store); | |
} | |
} | |
export function createInjectSagasStore(rootSaga, initialReducers, ...args) { | |
console.log('createInjectSagasStore', rootSaga, initialReducers, args); | |
original_store = createInjectStore(initialReducers, ...args); | |
original_store.injectedSagas = []; | |
injectSaga( | |
Object.keys(rootSaga)[0], | |
rootSaga[Object.keys(rootSaga)[0]], | |
false, | |
original_store | |
); | |
return original_store; | |
} | |
export const sagaMiddleware = createSagaMiddleware(); | |
export default createInjectSagasStore; |
This file contains hidden or 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, combineReducers } from 'redux'; | |
import set from 'lodash/set'; | |
import has from 'lodash/has'; | |
let original_store = {}; | |
let combine = combineReducers; | |
export function combineReducersRecurse(reducers) { | |
console.log('combineReducersRecurse', reducers); | |
// If this is a leaf or already combined. | |
if (typeof reducers === 'function') { | |
return reducers; | |
} | |
// If this is an object of functions, combine reducers. | |
if (typeof reducers === 'object') { | |
let combinedReducers = {}; | |
const keys = Object.keys(reducers); | |
for (let i = 0; i < keys.length; i++) { | |
const key = keys[i]; | |
combinedReducers[key] = combineReducersRecurse(reducers[key]); | |
} | |
return combine(combinedReducers); | |
} | |
// If we get here we have an invalid item in the reducer path. | |
const error = { | |
message: 'Invalid item in reducer tree', | |
item: reducers | |
}; | |
console.log(error); | |
throw new Error(error); | |
} | |
export function createInjectStore(initialReducers, ...args) { | |
console.log('createInjectStore', initialReducers, args); | |
// If last item is an object, it is overrides. | |
if (typeof args[args.length - 1] === 'object') { | |
const overrides = args.pop(); | |
// Allow overriding the combineReducers function such as with redux-immutable. | |
if ( | |
overrides.hasOwnProperty('combineReducers') && | |
typeof overrides.combineReducers === 'function' | |
) { | |
combine = overrides.combineReducers; | |
} | |
} | |
original_store = createStore( | |
combineReducersRecurse(initialReducers), | |
...args | |
); | |
original_store.injectedReducers = initialReducers; | |
return original_store; | |
} | |
export function reloadReducer(key, reducer, store = original_store) { | |
console.log('reloadReducer', key, reducer, store); | |
store.replaceReducer( | |
combineReducersRecurse({ ...store.injectedReducers, [key]: reducer }) | |
); | |
} | |
export function injectReducer( | |
key, | |
reducer, | |
force = false, | |
store = original_store | |
) { | |
console.log('injectReducer', key, reducer, force, store); | |
// If already set, do nothing. | |
if (!has(store.injectedReducers, key) || force) { | |
set(store.injectedReducers, key, reducer); | |
store.replaceReducer(combineReducersRecurse(store.injectedReducers)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment