Skip to content

Instantly share code, notes, and snippets.

const steps = {
STEP_A: { url: '/feature_1', nextStep: 'STEP_B' },
STEP_B: { url: '/feature_2', nextStep: 'STEP_C' },
STEP_C: { url: '/feature_3', nextStep: 'STEP_D' },
// ... and so on ...
};
const milestones = [
'SAVE_USER_PROFILE_SUCCESS',
'SAVE_PAYMENT_OPTIONS_SUCCESS',
'CONFIRM_SHOPPING_BASKET_SELECTION',
// ... and so on ...
];
const finalAction = 'SAVE_SHOPPING_ORDER_SUCCESS';
function setOnboardingStep(stepLabel) {
return {
type: 'SET_ONBOARDING_STEP',
payload: stepLabel
}
}
function addOnboardingMilestone(type) {
return {
type: 'ADD_ONBOARDING_MILESTONE',
function push(url) {
return {
type: 'PUSH_URL',
payload: url
}
}
function replace(url) {
return {
type: 'REPLACE_URL',
import { browserHistory } from 'react-router';
function locationReducer(state, action) {
switch (action.type) {
case 'PUSH_URL':
browserHistory.push(action.payload);
break;
case 'REPLACE_URL':
browserHistory.replace(action.payload);
break;
const exclusiveUrls = [
'/onboarding/route/1',
'/onboarding/route/2',
'/onboarding/route/3',
// ... and so on ...
];
let step = null;
const middleware = store => next => action => {
switch (action.type) {
case 'SET_ONBOARDING_STEP':
step = action.payload;
const { url } = steps[step];
// Make sure we "replace" instead of "push" when we have an on-boarding
// exclusive URL.
const redirectMethod = exclusiveUrls.indexOf(url) >= 0 ? replace : push;
if (step === finalStep) {
// Handle all LOCATION_CHANGE action from react-router-redux.
if (action.type === '@@router/LOCATION_CHANGE';) {
// Make sure the user is redirected away from on-boarding exclusive URLs.
if (exclusiveUrls.indexOf(action.payload.pathname) >= 0) {
store.dispatch( push('/somewhere/else') );
}
}
// If we're already on the last step, we don't need to steer the flow anymore,
if (milestones.indexOf(action.type) >= 0) {
const { nextStep } = states[step];
store.dispatch( setRegistrationStep(nextStep) );
}