Cerebral - Part 4, Tags and operators

3 minute read Published:

The intriguing use case of backticks.
Previous article in series

Table of Contents

In the previous part of this tutorial I’ve discussed how to update application state using actions.

We’ve implemented a simple function that used state’s get and set methods to change the count variable.

function changeCounter({props, state}){
  state.set("count", state.get("count") + props.param);

But doing this repeatedly for each state variable is incredibly redundant and I’ve been saying that Cerebral helps us write cleaner and more DRY code.

Let’s say we add another variable to the state that tracks the previous counter value. Do we need to write another action to update it? Nope. There’s a very clean solution for this.

Tags and operators

Since alot of operations on state are common, i.e. update, delete, splice, check condition, etc, Cerebral provides a set of operators to simplify your code.

Let’s see how we can use them.

We’ll add a state variable called ‘prevCount’ and will copy the ‘count’ to it before each operation.

Here’s how it’s done (showing only the changes):

import {set} from 'cerebral/operators'
import {state} from 'cerebral/tags'


state: {
    prevCount: 0,
    count: 0
  signals: {
       set(state`prevCount`, state`count`),

Let’s break down what we see here:

  1. No new functions were written

  2. We import set operator and state tag

  3. We add set to our signal chain and use the state tag to a) fetch current count b) set it to prevCount

Isn’t that nice and clean?

(full code here)

Anyone who’s reading this file will have an immidiate understanding of what’s going on, because the code reads like English:

When signal changeCounter is fired, do the following: set state prevCount to value of state count, then change counter and call the logAction.

This is what makes action chains with operators great.

And this is just scratching the surface.

Here are some examples of stuff you can do using operators and tags:

Update lists

import {merge, push, pop} from 'cerebral/operators'
import {state, props} from 'cerebral/tags'

export default [
  merge(state`some.object`, props`newObj`),
  push(state`some.list`, props`newItem`),

Debounce queries

import {set, debounce} from 'cerebral/operators'
import {state, props} from 'cerebral/tags'
import makeQueryRequest from '../chains/makeQueryRequest'

export default [
  set(state`query`, props`query`),
  debounce(500), {
    continue: makeQueryRequest,
    discard: []

Perform conditional execution

import {when, equals} from 'cerebral/operators'
import {state, props} from 'cerebral/tags'

export default [
  when(state`app.isAwesome`), {
    true: [],
    false: []
  equals(state`user.role`), {
    admin: [],
    user: [],
    otherwise: []

In it’s guts, an operator is actually an ‘action factory’, meaning, it’s a function returning an action. So you can easily write your own operators to clearly express your intentions and make your code clean.

For a full list of built-in operators, see: http://cerebraljs.com/docs/api/operators.html

comments powered by Disqus