2

I'm making a purchase flow where user must go through multiple routes to get to the final payments page. For example, on the first route you're entering mailing address information, on the second route you're configuring your purchase selection, third page you're putting in credit card information, etc. There are a total of about 5-6 pages/routes. How would I go about implementing a restriction on router so that people who have not gone through the first page cannot access the second page?

I'm using React Router 3.x, React router redux 4.x and also the React Boilerpate here. I read about using the onEnter function that React router provides but I cannot find any concrete examples on where to place that nor any specific documentation on executing something like what I'm trying to do, especially in conjunction with the React Boilerplate.

Does anyone have any ideas/guidance/resources on this?

For reference, my routes file looks something like this (pretty much the default routes file from the boilerplate) -

import { getAsyncInjectors } from 'utils/asyncInjectors';

const errorLoading = (err) => {
  console.error('Dynamic page loading failed', err); // eslint-disable-line no-console
};

const loadModule = (cb) => (componentModule) => {
  cb(null, componentModule.default);
};

export default function createRoutes(store) {
  // Create reusable async injectors using getAsyncInjectors factory
  const { injectReducer, injectSagas } = getAsyncInjectors(store); // eslint-disable-line no-unused-vars

  return [
    {
      path: '/paymentsPage/billing',
      name: 'billing',
      getComponent(nextState, cb) {
        const importModules = Promise.all([
          import('containers/Billing'),
        ]);

        const renderRoute = loadModule(cb);

        importModules.then(([component]) => {
          renderRoute(component);
        });

        importModules.catch(errorLoading);
      },
    },
    {
      path: '/paymentsPage/orgs',
      name: 'orgs',
      getComponent(nextState, cb) {
        const importModules = Promise.all([
          import('containers/Organization/reducer'),
          import('containers/Organization'),
        ]);

        const renderRoute = loadModule(cb);

        importModules.then(([reducer, component]) => {
          injectReducer('orgs', reducer.default);
          renderRoute(component);
        });

        importModules.catch(errorLoading);
      },
    }, {
      path: '/paymentsPage/amount',
      name: 'amount',
      getComponent(nextState, cb) {
        const importModules = Promise.all([
          import('containers/Donation/reducer'),
          import('containers/Donation'),
        ]);

        const renderRoute = loadModule(cb);

        importModules.then(([reducer, component]) => {
          injectReducer('amount', reducer.default);
          renderRoute(component);
        });

        importModules.catch(errorLoading);
      },
    }, {
      path: '/paymentsPage/finalPayment',
      name: 'finalPayment',
      getComponent(nextState, cb) {
        const importModules = Promise.all([
          import('containers/FinalPayment/reducer'),
          import('containers/FinalPayment'),
        ]);

        const renderRoute = loadModule(cb);

        importModules.then(([reducer, component]) => {
          injectReducer('finalPayment', reducer.ccInfoReducer);
          injectReducer('finalPayment', reducer.paymentReducer);
          renderRoute(component);
        });

        importModules.catch(errorLoading);
      },
    }, {
      path: '/paymentsPage/confirmation',
      name: 'confirmation',
      getComponent(nextState, cb) {
        const importModules = Promise.all([
          import('containers/Confirmation/reducer'),
          import('containers/Confirmation'),
        ]);

        const renderRoute = loadModule(cb);

        importModules.then(([reducer, component]) => {
          injectReducer('confirmation', reducer.default);
          renderRoute(component);
        });

        importModules.catch(errorLoading);
      },
    }, {
      path: '*',
      name: 'notfound',
      getComponent(nextState, cb) {
        import('containers/NotFoundPage')
          .then(loadModule(cb))
          .catch(errorLoading);
      },
    },
  ];
}
cssun25
  • 381
  • 1
  • 5
  • 13

1 Answers1

0

Technically, it's javascript, so any route is accessible with a little manipulation by the user. You could use redirects if you only want to encourage users to follow a certain set of routes. For example, you could check a flag in your state before the component mounts and if it's not set appropriately, redirect to the route you think the user should be on.

A more extreme solution could be to dynamically load react components from the server in a similar way to how webpack's dev server (and other build tools) works if you've ever used the hot reloading feature (disclaimer: I've never tried this so I'm not sure how well it would work). This would allow you some discrimination as to what routes are available to a user. This post (there are others as well) gives a rough outline of how this technique might work.

Community
  • 1
  • 1
user2027202827
  • 1,234
  • 11
  • 29