Get Started ➜
npm versiondownloadscommit activitylicense:MITfollowersconcent star

What can Concent offer you

simple core api

use 'run' to load model configuration, use 'register' to decorate class component, or use 'useConcent' to decorate function component.

zero-cost-use

no [Provider] any more, the decorated component can be interactive with store by [setState] directly.

friendly model configuration

except state, you can also define reducer、computed、watch and init optionally to cover all your scene.

flexible data consumption granularity

your can consume multi model data with state key level dependency.

progressive

except setState, you can also use dispatch or invoke to change state, separate your business logic and ui completely.

enhance component ability

support ref level computed 、watch、emit&on、setup etc.

highly consistent coding experience

no matter class component or function component, they can enjoy the same api call.

high performance rendering mechanism

working based on dependency mark、ref collection and state broadcast,built-in renderKey、lazyDispatch、delayBroadcast feature.

clean dom hierarchy

use reverse inheritance strategy for class component by default, to let your react dom tree keep clean.

middleware and plugin is supported

allow user customize middleware to intercept data changing behavior to do something else, allow user customize plugin to enhance concent ability.

de-centralization model configuration

allow user call configure api to configure you model definition, that means you can publish your component to npm with model.

model clone

allow user clone new model by existed model, to meet the abstract factory need.


How to install

npm install concent --save

//or 

yarn add concent

Key features preview

❤️Enjoy composition api with 🔥dependency collection🔥
import { run, useConcent } from "concent";

run();// startup concent
const setup = ctx => {
  const { initState, computed, watch, setState } = ctx;
  // init ref state
  initState({ count: 0 });
  // defined a computed fn, here dep is count, 
  // only count value changed will trigger this computed fn execute again
  computed("doubleCount", n => n.count * 2);
  // defined a watch fn, here dep is count, 
  // only count value changed will trigger this watch fn execute again
  watch("count", (n, o) => alert(`from ${o.count} to ${n.count}`));
  // return packed methods, they will been collected to ctx.settings
  return {
    inc: () => setState({ count: ctx.state.count + 1 }),
    dec: () => setState({ count: ctx.state.count - 1 })
  };
};

function Counter(){
  // deconstruct from ref ctx
  const { state, refComputed, settings } = useConcent({ setup });
  return (
    <>
      <h1>{state.count}</h1>
      <h1>{refComputed.doubleCount}</h1>
      <button onClick={settings.inc}>inc</button>
      <button onClick={settings.dec}>dec</button>
    </>
  );
}

❤️Easily share state and reuse logic between class and function
import { run, useConcent } from "concent";

const delay = (ms = 1000) => new Promise(r => setTimeout(r, ms));

run({// startup concent with module configuration  counter: {
    state: { count: 0 },// 【neccessary】,define module state
    reducer: {
      async complexUpdate(p, m, ac) {
        await delay();
        await ac.setState({ count: m.count + 10 });
        await delay();
        return { count: m.count + 10 };
      },
      simpleUpdate(p, m) {
        return { count: m.count - 100 };
      }
    },
    computed: {// 【optional】,define module computed
      doubleCount: n => n.count * 2,
      quadrupleCount: (n, o, f) => f.cuVal.doubleCount * 2,
    },
    watch: {// 【optional】,define module watch
      count: (n, o) => alert(`from ${o.count} to ${n.count}`)
    }
  }
});

const setup = ctx => {
  return {
    inc: () => ctx.setState({ count: ctx.state.count + 1 }),
    dec: () => ctx.setState({ count: ctx.state.count - 1 })
  };
};

function Counter() {
  const { state, moduleComputed, moduleReducer, settings } = 
    useConcent({ setup, module: "counter" });
  return <div> ui ... </div>
}

@register({ setup, module: "counter" })
class ClassCounter extends React.Component{
  render(){
    const { state, moduleComputed, moduleReducer, settings } = this.ctx;
    return <div> ui ... </div>
  }
}



Experience standard js concent project
Experience standard ts concent projectExplore more