Skip to content

vyckes/chifferobe

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chifferobe

Node version NPM Downloads Minified size License: MIT

A proxy based signals library that allows for small but powerful state management. It is build on top of three core principles:

  • Reactive: like any signals library, effects can be created that are executed once state is changed.
  • Immutable: data can be made immutable and cannot be mutated directly. Changes can be made via commands.
  • Access-layer: commands can be registered to the store. These are functions that can be invoked to make changes.

Example

Simple definition of a store

import { signal, effect } from "chifferobe";
// define a command
const increment =
  (state) =>
  (amount = 1) =>
    (state.count += amount);
// define the signal
const myStore = signal({ count: 0 }, { increment });
// interact with the signal
console.log(myStore.count); // 0
myStore.increment(2);
console.log(myStore.count); // 2

Basic effects

// Define an effect
let double = 0;
const dispose = effect(() => (double = myStore.count * 2));
console.log(double); // 4
myStore.increment(2);
console.log(double); // 8
// Remove the effect
dispose();

Effects based in multiple stores

const myStore1 = signal({ count: 0 }, { increment });
const myStore2 = signal({ count: 4 }, { increment });
// Define an effect
let sum = 0;
const dispose = effect(() => (sum = myStore1.count + myStore2.count));
console.log(sum); // 4
myStore.increment(2);
console.log(double); // 6
// Remove the effect
dispose();

TypeScript example

type CountStore = { count: number };
type CountCommands = {
  increment: (number?: number) => CountStore;
};

const initStore = { count: 0 };
const commands = {
  increment: (state) => (n) => {
    return { ...s, count: s.count + n };
  },
};

const store = signal<CountStore, CountCommands>(initStore, commands);

React hooks example

A generic React Hook implementation that automatically rerenders if the store value changes.

import { effect } from "chifferobe";
import { useLayoutEffect, useReducer } from "react";

export function useStore(store, key) {
  const [state, setState] = useState({});

  useLayoutEffect(() => {
    const dispose = effect(() => setState(store[key]));
    return () => dispose();
  }, []); //eslint-disable-line

  return state;
}

// Apply in a component
function MyButton() {
  // here a view on the data is being used in the hook
  const count = useReadStore(myStore, "count");
  return <button onClick={store.increment}>{`value ${count}`}</button>;
}

About

TypeScript implementation of event-driven proxy state.

Resources

License

Stars

Watchers

Forks

Packages

No packages published