Modules are the fundamental building blocks of a Cerebral application. They help you organize your application into logical units with their own state and behavior.
A module is an object with properties that define its behavior:
import App from 'cerebral'
const app = App({
state: {
title: 'My Project',
isLoading: false
},
sequences: {
loadData: [
// Actions to load data
]
},
providers: {
// Custom functionality
}
})
The most common module properties are:
As your application grows, you can organize it into nested modules:
import App from 'cerebral'
import userModule from './modules/user'
import postsModule from './modules/posts'
const app = App({
state: {
title: 'My Project'
},
modules: {
user: userModule,
posts: postsModule
}
})
Each module can have its own state, sequences, and providers that will be namespaced under the module’s path.
Let’s create a simple module for handling users:
// modules/user/index.js
import * as sequences from './sequences'
import * as providers from './providers'
export default {
state: {
currentUser: null,
isLoading: false,
error: null
},
sequences,
providers
}
// modules/user/sequences.js
import { set } from 'cerebral/factories'
import { state, props } from 'cerebral'
import * as actions from './actions'
export const fetchUser = [
set(state`user.isLoading`, true),
actions.fetchUser,
{
success: [
set(state`user.currentUser`, props`user`),
set(state`user.isLoading`, false)
],
error: [
set(state`user.error`, props`error`),
set(state`user.isLoading`, false)
]
}
]
The state from all modules is merged into one big state tree:
// From root module:
{
title: 'My Project',
user: {
currentUser: null,
isLoading: false,
error: null
},
posts: {
items: [],
isLoading: false
}
}
You access state using paths:
// In components
connect({
title: state`title`,
user: state`user.currentUser`,
isLoadingUser: state`user.isLoading`
})
// In actions
function myAction({ store }) {
store.set(state`user.isLoading`, true)
}
You can use moduleState
to refer to state relative to the current module:
import { moduleState } from 'cerebral'
// In a sequence in the user module:
;[
set(moduleState`isLoading`, true), // Sets user.isLoading
actions.fetchUser,
set(moduleState`isLoading`, false) // Sets user.isLoading
]
This makes your modules more portable as they don’t need to know their exact path in the state tree.
For more advanced organization, you can create module factories that generate the module based on its context:
const userModule = ({ name, path, app }) => ({
state: {
users: {},
currentPage: 1
},
sequences: {
initialize: [
({ store }) => {
console.log(`Module "${name}" initialized at path "${path}"`)
store.set(moduleState`initialized`, true)
}
]
}
})
Modules allow you to:
In the next sections, we’ll explore other core Cerebral concepts that work with modules to help you build sophisticated applications.