Creating Subspaces

Consider an application whose store is created like:

import { createStore, combineReducers } from 'redux'

const subApp1 = (state = { value: 1 }, action) => {
    switch (action.type) {
        case 'INCREMENT_APP_1':
            return { ...state, value: state.value + 1 }
        default:
            return state
    }
}

const subApp2 = (state = { value: 2 }, action) => {
    switch (action.type) {
        case 'INCREMENT_APP_2':
            return { ...state, value: state.value + 1 }
        default:
            return state
    }
}

const reducer = combineReducers({
    subApp1,
    subApp2
})

const store = createStore(reducer)

This store's state will now look like:

{
    "subApp1": {
        "value": 1
    },
    "subApp2": {
        "value": 2
    }
}

We can create a subspace for subApp1 using the subspace function with a selector mapping it's state:

import { subspace } from 'redux-subspace'

const subApp1Store = subspace((state) => state.subApp1)(store)

In the above example, subApp1Store looks like a regular store, but the state returned from getState() is that returned by the selector:

console.log('subApp1 state:', subApp1Store.getState()) // { "value": 1 }

Calling dispatch on subApp1Store will delegate the action handling to the root store to pass to it's reducer:

subApp1Store.dispatch({ type: 'INCREMENT_APP_1' })

console.log('subApp1 state:', subApp1Store.getState()) // { "value": 2 }

console.log('store state:', store.getState()) // { "subApp1": { value: 2 }, "subApp2": { value: 2 } }

Obviously, we could just have easily created a subspace for subapp2:

const subApp2Store = subspace((state) => state.subApp2)(store)

console.log('subApp2 state:', subApp2Store.getState()) // { "value": 2 }

subApp2Store.dispatch({ type: 'INCREMENT_APP_2' })

console.log('subApp2 state:', subApp2Store.getState()) // { "value": 3 }

console.log('store state:', store.getState()) // { "subApp1": { value: 2 }, "subApp2": { value: 3 } }

However, in this scenario, if 'INCREMENT_APP_2' was dispatched by subApp1Store the state for subApp2 would still update

subApp1Store.dispatch({ type: 'INCREMENT_APP_2' })

console.log('subApp1 state:', subApp1Store.getState()) // { "value": 2 }

console.log('subApp2 state:', subApp2Store.getState()) // { "value": 4 }

console.log('store state:', store.getState()) // { "subApp1": { value: 2 }, "subApp2": { value: 4 } }

This may be fine for if you can guarantee all action types are unique across all the sub-applications, but if two or more sub-applications want to use the same action type, then there may by unwanted state changes when unrelated actions are dispatched.

In the next section we will look at how we can namespace our sub-applications so that they don't affect each other.

results matching ""

    No results matching ""