Skip to content

Instantly share code, notes, and snippets.

@bradennapier
Last active June 19, 2017 04:56
Show Gist options
  • Save bradennapier/4f8afd43215327304fddf27c819ad035 to your computer and use it in GitHub Desktop.
Save bradennapier/4f8afd43215327304fddf27c819ad035 to your computer and use it in GitHub Desktop.
redux-saga process with code-splitting & hot reloading
import { Process } from 'redux-saga-process';
import { call, put } from 'redux-saga/effects';
import { createSelector } from 'reselect';
import { createTaskManager } from 'saga-task-manager';
import startUserPositionObserver from 'saga-geolocation-observer';
import handleUserPosition from './sagas/handleUserPosition';
const nilLocation = {
accuracy: undefined,
latitude: undefined,
longitude: undefined,
lastUpdated: undefined,
};
const build_type = (type, config) =>
`${config.types.prefix}_${config.types[type]}`;
const build_config = config => ({
reduces: 'user',
pid: 'userLocation',
stateKey: 'location',
exports: ['actions', 'selectors'],
autoStart: false,
log: false,
initialState: nilLocation,
positionOptions: {
enableHighAccuracy: true,
},
...config,
actions: {
start: 'geolocationStart',
stop: 'geolocationStop',
...config.aations,
},
types: {
prefix: 'USER',
location: 'LOCATION',
...config.types,
},
});
export default (_config, callback) => {
const config = build_config(_config);
const processSelectors = {};
const stateKeySelector = state =>
state[config.reduces] && state[config.reduces][config.stateKey];
processSelectors.userLocation = createSelector(
stateKeySelector,
userLocation => ({
accuracy: userLocation.accuracy,
latitude: userLocation.latitude,
longitude: userLocation.longitude,
lastUpdated: userLocation.lastUpdated,
}),
);
const processActionRoutes = {
[config.actions.stop]: 'handleStop',
[config.actions.start]: 'handleStart',
};
const processActionCreators = {
[config.actions.stop]: null,
[config.actions.start]: null,
};
const processInitialState = {
[config.stateKey]: config.initialState,
};
const processReducer = {
[build_type('location', config)]: (state, action) => ({
...state,
[config.stateKey]: {
accuracy: action.accuracy,
latitude: action.latitude,
longitude: action.longitude,
lastUpdated: action.lastUpdated,
},
}),
};
const processConfig = {
pid: config.pid,
reduces: config.reduces,
};
return class GeoLocationProcess extends Process {
static config = processConfig;
static exports = config.exports;
static initialState = processInitialState;
static actionCreators = processActionCreators;
static actionRoutes = processActionRoutes;
static selectors = processSelectors;
static reducer = processReducer;
constructor(processID, proc) {
super(processID, proc);
this.state = {
coords: undefined,
};
this.task = createTaskManager(processID, {
name: build_type('location', config),
log: true,
});
}
*handleStop() {
yield call([this.task, this.task.cancel], 'observers');
}
*handleStart() {
const handlers = {
onEvent: [this, this.handleEvent],
onError: [this, this.handleError],
onCancel: [this, this.handleCancelled],
};
yield* this.task.create(
'observers',
'geolocation',
startUserPositionObserver,
'user-geolocation-observer',
config.positionOptions,
handlers,
);
}
*handleEvent(event, value, uid) {
switch (event) {
case 'watchPosition': {
const position = yield call([this, handleUserPosition], value);
if (position) {
yield put({
type: build_type('location', config),
...position,
});
}
break;
}
}
}
*handleError(event, error, uid) {
console.error(`[saga-process-geolocation]: ${error.message}`);
}
*handleCancelled(event, uid) {
console.warn('Geolocation Observer Cancelled');
// console.warn(event, uid)
}
*processStarts() {
if (config.autoStart) {
yield call([this, this.handleStart]);
}
}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment