DEV Community

张一凡
张一凡

Posted on

easy-model: model-first state with IoC and deep watching

TL;DR

  • Class-based models: fields are state, methods are logic.
  • Hooks-first API: useModel, useInstance, useWatcher.
  • Deep watching and DI are built in.
  • Instance caching by args makes state partitioning natural.

Why it exists

Most state libraries start with a store. easy-model starts with a model class. That shift makes domain logic cohesive and testable. You describe business behavior once, then subscribe to it in React with minimal glue.

A minimal example

import { useModel, useWatcher } from "easy-model";

class CounterModel {
  count = 0;
  label: string;
  constructor(initial = 0, label = "Counter") {
    this.count = initial;
    this.label = label;
  }
  increment() {
    this.count += 1;
  }
  decrement() {
    this.count -= 1;
  }
}

function Counter() {
  const counter = useModel(CounterModel, [0, "Demo"]);

  useWatcher(counter, (keys, prev, next) => {
    console.log("changed:", keys.join("."), prev, "->", next);
  });

  return (
    <div>
      <h2>{counter.label}</h2>
      <div>{counter.count}</div>
      <button onClick={() => counter.decrement()}>-</button>
      <button onClick={() => counter.increment()}>+</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Practical wins

  • Cohesive logic: no action/reducer splits.
  • Deep watching: observe nested changes without extra plumbing.
  • DI built in: explicit dependencies, easier tests.
  • Natural partitioning: instance caching by args.

If your team already models domain logic with classes, easy-model feels natural with minimal migration cost.

GitHub: easy-model

npm: @e7w/easy-model

Top comments (0)