Actions are the building blocks of sequences in Cerebral. When actions run they receive a context object with tools and values to interact with your app.
function myAction(context) {
// Use context to access state, props, etc.
}
The context is populated by Cerebral and can be extended with custom providers. By default, Cerebral includes the following on the context:
When you trigger a sequence you can pass it a payload. This payload is the starting point of the props for the sequence:
// Define a sequence with multiple actions
const mySequence = [actionA, actionB]
// Trigger the sequence with initial props
mySequence({
foo: 'bar'
})
The first action will receive the payload passed to the sequence:
function actionA({ props }) {
props // {foo: "bar"}
return {
bar: 'baz'
}
}
By returning an object, you extend the props for the next action:
function actionB({ props }) {
props // {foo: "bar", bar: "baz"}
}
Return values from actions, either directly or from a promise, are merged with existing props for subsequent actions to use.
To change the state of your application, use the store API:
function setSomething({ store }) {
store.set('some.path.foo', 'bar')
}
Cerebral uses a direct mutation approach instead of relying on immutability patterns. Instead of first accessing a value and then operating on it, you specify the operation first and then the path to the value:
// Traditional approach
someArray.push('newItem')
// With Cerebral
store.push('path.to.array', 'newItem')
This approach enables Cerebral to:
Available store methods include:
The path property is only available when your action is followed by a paths object:
import * as actions from './actions'
export default [
actions.actionA,
actions.actionB,
{
success: actions.actionC,
error: actions.actionD
}
]
In this example, only actionB
has access to the path property, allowing it to choose between the “success” and “error” paths:
function actionB({ path }) {
// Choose which path to take
if (someCondition) {
return path.success()
} else {
return path.error()
}
}
You can access state, props, computed values, and sequences using the get
function:
import { state, props } from 'cerebral'
function someAction({ get }) {
const foo = get(state`foo`) // Get state value
const user = get(state`users.${props`userId`}`) // Dynamic path
}
You can also use object notation (like state.foo
) with the babel-plugin-cerebral.
The resolve
utility allows you to work with tags and values at a lower level. get
is actually a wrapper around resolve
:
function someActionFactory(someArgument) {
function someAction({ resolve }) {
// Resolve any value, including tags
const value = resolve.value(someArgument)
// Check if an argument is a tag
if (resolve.isTag(someArgument)) {
// Get the path string of a tag
const path = resolve.path(someArgument)
}
}
return someAction
}
This is particularly useful when creating factories that accept a mix of static values and tags.