Convert Figma logo to code with AI

cerebral logocerebral

Declarative state and side effects management for popular JavaScript frameworks

1,991
125
1,991
12

Top Related Projects

60,936

A JS library for predictable global state management

27,618

Simple, scalable state management.

28,431

🗃️ Centralized State Management for Vue.js.

Reactive State for Angular

17,488

Application Architecture for Building User Interfaces

30,950

A reactive programming library for JavaScript

Quick Overview

Cerebral is a state management library for JavaScript applications. It provides a declarative and centralized approach to managing application state, side effects, and business logic. Cerebral aims to simplify complex state management scenarios and improve developer productivity.

Pros

  • Centralized state management with a single state tree
  • Powerful debugging tools with time-travel debugging
  • Supports both React and Vue.js frameworks
  • Modular architecture allowing for easy scaling of large applications

Cons

  • Steeper learning curve compared to simpler state management solutions
  • Requires additional setup and configuration
  • May be overkill for small to medium-sized applications
  • Less community support compared to more popular state management libraries

Code Examples

  1. Defining a state tree and actions:
import { Controller, Module } from 'cerebral'

const app = Module({
  state: {
    count: 0
  },
  signals: {
    increment: ({ state }) => state.set('count', state.get('count') + 1),
    decrement: ({ state }) => state.set('count', state.get('count') - 1)
  }
})

const controller = Controller(app)
  1. Using Cerebral with React:
import React from 'react'
import { connect } from '@cerebral/react'

const Counter = connect(
  {
    count: state`count`,
    increment: signal`increment`,
    decrement: signal`decrement`
  },
  function Counter({ count, increment, decrement }) {
    return (
      <div>
        <h1>{count}</h1>
        <button onClick={() => increment()}>+</button>
        <button onClick={() => decrement()}>-</button>
      </div>
    )
  }
)
  1. Defining and using computed state:
import { Compute } from 'cerebral'

const doubleCount = Compute(
  state`count`,
  (count) => count * 2
)

const DoubleCounter = connect(
  {
    doubleCount
  },
  function DoubleCounter({ doubleCount }) {
    return <h2>Double count: {doubleCount}</h2>
  }
)

Getting Started

To get started with Cerebral, follow these steps:

  1. Install Cerebral and its React bindings:

    npm install cerebral @cerebral/react
    
  2. Create a Cerebral controller:

    import { Controller, Module } from 'cerebral'
    
    const app = Module({
      state: {
        // Your initial state
      },
      signals: {
        // Your signals (actions)
      }
    })
    
    const controller = Controller(app)
    
  3. Wrap your React app with the Cerebral provider:

    import { Container } from '@cerebral/react'
    
    ReactDOM.render(
      <Container controller={controller}>
        <App />
      </Container>,
      document.getElementById('root')
    )
    
  4. Connect your components to the Cerebral state:

    import { connect } from '@cerebral/react'
    
    export default connect(
      {
        // Map state and signals
      },
      function YourComponent(props) {
        // Your component logic
      }
    )
    

Competitor Comparisons

60,936

A JS library for predictable global state management

Pros of Redux

  • Larger ecosystem and community support
  • More widespread adoption, leading to better documentation and resources
  • Simpler learning curve for developers familiar with Flux architecture

Cons of Redux

  • More boilerplate code required for setup and state management
  • Can become complex in large applications with many actions and reducers
  • Less opinionated, which may lead to inconsistent implementations across projects

Code Comparison

Redux:

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    default:
      return state;
  }
};

Cerebral:

export const increment = ({ state }) => {
  state.set('count', state.get('count') + 1);
};

Redux typically uses switch statements in reducers to handle actions, while Cerebral uses a more declarative approach with state mutations. Cerebral's syntax is often more concise, but Redux's explicit nature can make it easier to understand the flow of data in larger applications.

Both libraries aim to simplify state management in complex applications, but they take different approaches. Redux focuses on predictability and a single source of truth, while Cerebral emphasizes declarative state changes and side-effect management. The choice between them often depends on project requirements and team preferences.

27,618

Simple, scalable state management.

Pros of MobX

  • Simpler learning curve and more intuitive API
  • Better performance for large-scale applications
  • More flexible and less opinionated about application structure

Cons of MobX

  • Less predictable state changes due to mutable state
  • Potential for overuse of observables, leading to unnecessary re-renders
  • Lack of built-in time-travel debugging

Code Comparison

MobX:

import { makeObservable, observable, action } from "mobx";

class TodoStore {
  todos = [];

  constructor() {
    makeObservable(this, {
      todos: observable,
      addTodo: action
    });
  }

  addTodo(text) {
    this.todos.push({ text, completed: false });
  }
}

Cerebral:

import { state, sequence } from 'cerebral'

export const state = {
  todos: []
}

export const addTodo = sequence('Add todo', [
  ({ state, props }) => {
    state.todos.push({ text: props.text, completed: false })
  }
])

Both MobX and Cerebral are state management libraries for JavaScript applications, but they have different approaches. MobX focuses on reactive programming and uses observables, while Cerebral uses a more explicit signal-state-model architecture. MobX is generally easier to learn and integrate into existing projects, while Cerebral provides a more structured approach to state management.

28,431

🗃️ Centralized State Management for Vue.js.

Pros of Vuex

  • Tightly integrated with Vue.js ecosystem, providing seamless state management for Vue applications
  • Simple and intuitive API, making it easy to learn and use for developers familiar with Vue
  • Extensive documentation and large community support

Cons of Vuex

  • Limited to Vue.js applications, not suitable for other frameworks or vanilla JavaScript
  • Can become complex in large applications with many modules and nested states

Code Comparison

Vuex:

const store = new Vuex.Store({
  state: { count: 0 },
  mutations: {
    increment(state) { state.count++ }
  }
})

Cerebral:

const controller = Controller({
  state: { count: 0 },
  signals: {
    increment: [({ state }) => state.set('count', state.get('count') + 1)]
  }
})

Both Vuex and Cerebral provide state management solutions, but Vuex is specifically designed for Vue.js applications, while Cerebral is framework-agnostic. Vuex offers a more straightforward API for simple use cases, whereas Cerebral provides a more flexible and powerful approach to complex state management scenarios.

Reactive State for Angular

Pros of NgRx

  • Tightly integrated with Angular, providing a seamless experience for Angular developers
  • Extensive ecosystem with additional libraries like @ngrx/effects and @ngrx/entity
  • Strong community support and regular updates

Cons of NgRx

  • Steeper learning curve, especially for developers new to Redux concepts
  • More boilerplate code required compared to Cerebral
  • Can be overkill for smaller applications

Code Comparison

NgRx:

@Component({...})
export class MyComponent {
  data$ = this.store.select(selectData);
  constructor(private store: Store) {}
  loadData() {
    this.store.dispatch(loadData());
  }
}

Cerebral:

connect({
  data: state`data`,
  loadData: signal`loadData`
},
function MyComponent({ data, loadData }) {
  return <button onClick={() => loadData()}>Load Data</button>
}

Both NgRx and Cerebral are state management solutions, but they differ in their approach and ecosystem. NgRx is specifically designed for Angular applications, while Cerebral is framework-agnostic. NgRx follows a more traditional Redux pattern, whereas Cerebral uses a unique signal-state model. The code comparison shows how actions/signals are dispatched in each library, with NgRx requiring more setup but offering tighter TypeScript integration.

17,488

Application Architecture for Building User Interfaces

Pros of Flux

  • Simpler learning curve due to its straightforward unidirectional data flow concept
  • Better integration with React ecosystem, being developed by Facebook
  • More widespread adoption and larger community support

Cons of Flux

  • Less flexibility in handling complex state management scenarios
  • Lack of built-in tools for handling side effects and asynchronous operations
  • Requires more boilerplate code for larger applications

Code Comparison

Flux:

var AppDispatcher = require('./AppDispatcher');
var TodoConstants = require('./TodoConstants');

var TodoActions = {
  create: function(text) {
    AppDispatcher.dispatch({
      actionType: TodoConstants.TODO_CREATE,
      text: text
    });
  }
};

Cerebral:

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

export const createTodo = ({props, store}) => {
  store.set(state`todos.${props.id}`, props.todo)
}

Cerebral offers a more declarative approach to state management, with built-in operators and tags for easier state manipulation. Flux, on the other hand, relies on a more traditional dispatch-based system, which can be more verbose but is also more familiar to developers coming from other frameworks.

30,950

A reactive programming library for JavaScript

Pros of RxJS

  • Widely adopted and mature ecosystem with extensive documentation
  • Powerful operators for complex data transformations and event handling
  • Cross-platform support (browser, Node.js, and mobile)

Cons of RxJS

  • Steeper learning curve due to its functional reactive programming paradigm
  • Can lead to increased complexity for simple use cases
  • Potential performance overhead for large-scale applications

Code Comparison

RxJS:

import { fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';

fromEvent(input, 'input')
  .pipe(
    debounceTime(300),
    map(event => event.target.value)
  )
  .subscribe(value => console.log(value));

Cerebral:

import { state, sequence } from 'cerebral';

export const updateInput = sequence('updateInput', [
  ({ props, store }) => {
    store.set(state.inputValue, props.value);
  },
]);

RxJS excels in handling complex event streams and asynchronous operations, while Cerebral provides a more structured approach to state management. RxJS offers greater flexibility but may require more boilerplate, whereas Cerebral aims for simplicity in defining state changes. The choice between the two depends on the specific requirements of your project and your team's familiarity with reactive programming concepts.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Cerebral

A declarative state and side effects management solution for popular JavaScript frameworks

NPM version Build status Coverage Status bitHound Score Commitizen friendly Discord

Maintainer needed

https://gist.github.com/christianalfoni/f1c4bfe320dcb24c403635d9bca3fa40

Documentation

Contribute

The entire Cerebral codebase has been rewritten to encourage contributions. The code is cleaned up, commented and all code is in a "monorepo". That means you can run tests across projects and general management of the code is simplified a lot.

  1. Clone the monorepo: git clone https://github.com/cerebral/cerebral.git
  2. In root: npm install

The packages are located under packages folder and there is no need to run npm install for each package.

Using monorepo for your own apps

If you want to use Cerebral 2 directly from your cloned repo, you can create a symlinks for following directories into the node_modules directory of your app:

  • packages/node_modules/cerebral
  • packages/node_modules/function-tree
  • packages/node_modules/@cerebral

If your app and the cerebral monorepo are in the same folder you can do from inside your app directory:

$ ln -s ../../cerebral/packages/node_modules/cerebral/ node_modules/
# ...

Just remember to unlink the package before installing it from npm:

$ unlink node_modules/cerebral
# ...

Running demos

Go to the respective packages/demos/some-demo-folder and run npm start

Testing

You can run all tests in all packages from root:

npm test

Or you can run tests for specific packages by going to package root and do the same:

npm test

Changing the code

When you make a code change you should create a branch first. When the code is changed and backed up by a test you can commit it from the root using:

npm run commit

This will give you a guide to creating a commit message. Then you just push and create a pull request as normal on Github.

Release process

  • Review and merge PRs into next branch. It is safe to use "Update branch", the commit created by Github will not be part of next history
  • If changes to repo-cooker, clean Travis NPM cache
  • From command line:
$ git checkout next
$ git pull
$ npm install # make sure any new dependencies are installed
$ npm install --no-save repo-cooker # needed to test release, make sure you have latest
$ npm run release # and check release notes
$ git checkout master
$ git pull
$ git merge --ff-only next
$ git push

NPM DownloadsLast 30 Days