Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
🐻 Valoo: just the bare necessities of state management. 150b / 120b. https://npm.im/valoo

🐻 valoo

just the bare necessities of state management.

Usage

Hotlink it from https://unpkg.com/valoo.

See Interactive Codepen Demo.

import valoo from 'https://unpkg.com/valoo'

// create an observable value:
const num = valoo(42)

// subscribe to value changes:
const off = num.on( v => console.log(v) )

// unsubscribe that listener:
off()

// set the value, invoking any listeners:
num(43)

// get the current value:
num()  // 43

Other Versions

  • valoo-lite.mjs: lighter 120b version, but doesn't support unsubscribing.
  • valoo-original.mjs: v1-compatible, with subscribe handled via overloading.

Credit

The idea here was first implemented in Mithril. I believe the subscription mechanism is new though.

License

Apache-2.0. Copyright 2018 Google LLC.

node_modules
package-lock.json
dist
README.md
{
"name": "valoo",
"version": "2.1.0",
"module": "valoo.mjs",
"main": "dist/valoo.js",
"types": "./valoo.d.ts",
"license": "Apache-2.0",
"scripts": {
"prepublishOnly": "cp *valoo.md README.md;microbundle valoo.mjs"
},
"devDependencies": {
"microbundle": "^0.5.1"
}
}
export default (v, cb=[]) => c => c===void 0 ? v : c.call ? cb.push(c) : cb.map(f=>f(v=c)) && v
export default (v, cb=[]) => c => {
if (c===void 0) return v
if (c.call) return cb.splice.bind(cb, cb.push(c)-1, 1, 0)
v = c; for (c of cb) c && c(v)
}
declare module "valoo" {
namespace valoo {
type Disposer = () => void;
interface Observable<T> {
(): T;
(value: T): void;
on(fn: (value: T) => void): Disposer;
}
}
function valoo<T = any>(value: T): valoo.Observable<T>;
export = valoo;
}
export default function valoo(v) {
const cb = [];
function value(c) {
if (arguments.length) cb.map(f => { f && f(v=c); });
return v;
}
value.on = c => {
const i = cb.push(c)-1;
return () => { cb[i] = 0; };
};
return value;
}
@jamiebuilds

This comment has been minimized.

Copy link

@jamiebuilds jamiebuilds commented Jul 6, 2018

Who hurt you @developit

@developit

This comment has been minimized.

Copy link
Owner Author

@developit developit commented Jul 6, 2018

X

@WebReflection

This comment has been minimized.

Copy link

@WebReflection WebReflection commented Jul 6, 2018

I regret already I've PR'd .mjs extension to unpkg, but beside that, I think this could easily land as ES3 syntax in there.

function valoo(v, cb) {
  cb = cb || [];
  return function (c) {
    if (c === void 0) return v;
    if (c.call) return cb.splice.bind(cb, cb.push(c) - 1, 1, null);
    v = c;
    for (var i = 0, l = cb.length; i < l; i++)
      cb[i] && cb[i](v);
  };
}
var num = valoo(42);
var sub = num(function (v) { console.log(v); });

num(43);

sub();

num();

Nice one though.

@developit

This comment has been minimized.

Copy link
Owner Author

@developit developit commented Jul 6, 2018

@WebReflection ah good call on the for..of - I did publish ES3 & UMD, they're just ignored in the gist:
https://unpkg.com/valoo@1.0.2/dist/valoo.js

@hakimelek

This comment has been minimized.

Copy link

@hakimelek hakimelek commented Jul 6, 2018

+1 plus you can comment on the repo!

@MoritzKn

This comment has been minimized.

Copy link

@MoritzKn MoritzKn commented Jul 9, 2018

Is there a reason you use map() to iterate over the cb array instead of forEach()?

@developit

This comment has been minimized.

Copy link
Owner Author

@developit developit commented Jul 14, 2018

@MoritzKn: fewer bytes!

2.1.0 is out and how ships with a TypeScript definition. Thanks @marvinhagemeister!

@ezekielchentnik

This comment has been minimized.

Copy link

@ezekielchentnik ezekielchentnik commented Oct 28, 2018

kind of cool, use with react's new hook api

import valoo from "valoo";
import { useState, useEffect } from "react";

export default function useValoo(value){
    const [, set] = useState(value);
    const val = valoo(value);
    useEffect(() => val.on(set), [val]);
    return val;
}

function Num(){
    const num = useValoo(42)
    return (
        <div onClick={() => num(43)}>{num()}</div>
    );
}

in react, you could also do this

function useValue(value){
    const [state, set] = useState(value);
    return val => val === void 0 ? state : set(val);
}
@thinkofher

This comment has been minimized.

Copy link

@thinkofher thinkofher commented Nov 13, 2020

Wow, that's all I need for my project right now in case of state managment. I really appreciate it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment