How to split routes to different files with Redux and React-router?

762 views Asked by At

I have many routes in my application. Each has an onEnter method that loads data from an API and fires an action (thunk) on the store.

const routeConfig = [
    {path: '/tutorial/:tutorialId', component: Tutorial, onEnter: tutorialEnter},
    {path: '/session/:sessionId', component: App, onEnter: sessionEnter},
    {path: '/session/:userId/:sessionId', component: App, onEnter: userSessionEnter},
    {path: '/template/:language/:sessionId', component: App, onEnter: templateEditEnter},
    {path: '/snippet/:language/:appType/:sessionId', component: App, onEnter: snippetEditEnter},
    {path: '/prepare/:sessionId', component: Library, onEnter: galleryPrepareEnter},
    {path: '/launch/:comboId', component: Launch, onEnter: launchEnter},
    ... more

];

const renderStore = () => {
    rootElement = document.getElementById('root')

    render(
        <MuiThemeProvider>
            <div className="root">
                <Provider store={store}>
                    <Router history={history} routes={routeConfig} onUpdate={onPageView}/>
                </Provider>
            </div>
        </MuiThemeProvider>,

        rootElement
    );
}

example for an OnEnter method:

const launchEnter = (location) => {
    let {comboId} = location.params;

    store.dispatch(appActions.getComboDetails(comboId))
    store.dispatch(appActions.getBuildRequestsForCombo(comboId))
}

I want to split the routes and OnEnter scripts into different files. I can create a method that returns an array with some of the routes but how do I get access to the store? Two ideas which I had seemed flawed:

Idea #1 - wrapping the store. LaunchRoutes.js:

export const getRoutes = (store) => {

    const launchEnter = (location) => {
        let {comboId} = location.params;

        store.dispatch(appActions.getComboDetails(comboId))
        store.dispatch(appActions.getBuildRequestsForCombo(comboId))
    }

    return [
        {path: '/launch/:comboId', component: Launch, onEnter: launchEnter},
    ];
}

This doesn't feel right to have the store locked in this closure.

Idea #2 - accessing the store via a global

const store = window.store;

const launchEnter = (location) => {
    let {comboId} = location.params;

    store.dispatch(appActions.getComboDetails(comboId))
    store.dispatch(appActions.getBuildRequestsForCombo(comboId))
}

export const getRoutes = (store) => {

    return [
        {path: '/launch/:comboId', component: Launch, onEnter: launchEnter},
    ];
}

This even seems a worst idea than the first one using the window as a cheap way out of it.

Any ideas how to properly split the routes?

1

There are 1 answers

0
Paul S On

One possible solution would be to go the same route as react-router does with browserHistory and hashHistory, which would be to create a store module and export your store instance from there.

This may or may not work based on your code structure, but essentially you would have a store.js:

import { createStore } from 'redux'
import reducers from './reducers'

export default createStore(reducers)

You could then import the store throughout your project wherever you need to interact with it.

// index.js
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'

import store from './store'

render((
  <Provider store={store}>...</Provider>
), holder)

and

// launchEnter.js
import store from './store'

const launchEnter = (location) => {
  let {comboId} = location.params;
  store.dispatch(appActions.getComboDetails(comboId))
  store.dispatch(appActions.getBuildRequestsForCombo(comboId))
}