Concent
State management that tailored for react, it is simple, predictable, progre...
README
⚡️ State management that tailored for react, it is simple, predictable, progressive and efficient.
🐮Introduction
Concent is an amazing state management tool, supported by a healthy middleware ecosystem and excellent devtools. It is a predictable, zero-invasive, progressive, high-performance react development framework!
Concent encourages simplicity. It saves you the hassle of creating boilerplate code and gives powerful tools with a moderate learning curve, suitable for both experienced and inexperienced developers alike.
recommend next verion lib: helux
✨Features
Provider less
Render context injected automatically (no any annoying boilerplate code)
Dependency collection at runtime (state & computed)
Unified logic reuse of class and function components
Optional Compostion api support
Optional modular development support(state、reducer、computed、watch、lifecycle)
High performance renderKey mechanism
Centralization and De-centralization module configuration both support
Dynamic module configuration support
Reducer combination support
React Devtools support
Hot-reload support
SSR&Nextjs support
React-native support
💻 Playground
Templates
A best practise project(git) building by concent & typescript.
- ```sh
- $ git clone https://github.com/tnfe/concent-pro (dev with webpack)
- $ git clone https://github.com/tnfe/vite-concent-pro (dev with vite)
- ```
Install by npx command
- ```sh
- $ npx create-react-app my-app --template concent-ts
- ```
or clone its source code by git command
- ```sh
- $ git clone https://github.com/concentjs/cra-project-concent-ts
- ```
Key features snippet
Online case
👨🏽Docs
Visit official website https://concentjs.github.io/concent-doc to learn more.
📦Quick start
Make sure you have installed nodejs。
Install
- ```sh
- $ npm i --save concent
- ```
or yarn command
- ```sh
- $ yarn add concent
- ```
Minimal example
See how easy it is to use concent to manage react state.
- ```js
- import { run, register, useConcent } from 'concent';
- // 1️⃣ Configure models
- run({
- counter: {// declare a moudle named 'counter'
- state: { num: 1, numBig: 100 }, // define state
- },
- // you can also put another module here.
- });
- // 2️⃣ Now the react component can work with concent
- @register('counter') // 👈 decorate your component with register
- class DemoCls extends React.Component{
- // commit state to store and broadcast to other refs which also belong to counter module
- inc = ()=> this.setState({num: this.state.num + 1})
- render(){
- // here if read num, it means current ins render dep keys is ['num']
- return <button onClick={this.inc}>{this.state.num}</button>
- }
- }
- function DemoFn(){
- const { state, setState } = useConcent('counter'); // 👈 call useConcent hook in fn component
- const inc = ()=> setState({num: state.num + 1});
- return <button onClick={inc}>{state.num}</button>
- }
- ```
Complete example
Move logic to reducer and define computed,watch,lifecycle
try edit this demo、 👉better js demo、👉better ts demo
- ```js
- import { run, register, useConcent, defWatch } from 'concent';
- run({
- counter: {
- state: { num: 1, numBig: 100 },
- computed: {
- numx2: ({ num }) => num * 2, // only num changed will trigger this fn
- numx2plusBig: ({ numBig }, o, f) => f.cuVal.numx2 + numBig // reuse computed reslult
- },
- reducer: {
- initState: () => ({ num: 8, numBig: 800 }),
- add: (payload, moduleState, actionCtx) => ({ num: moduleState.num + 1 }),
- addBig: (p, m, ac) => ({ numBig: m.numBig + 100 }),
- asyncAdd: async (p, m, ac) => {
- await delay(1000);
- return { num: m.num + 1 };
- },
- addSmallAndBig: async (p, m, ac) => {
- // hate string literal? see https://codesandbox.io/s/combine-reducers-better-7u3t9
- await ac.dispatch("add");
- await ac.dispatch("addBig");
- }
- },
- watch: {
- numChange: defWatch(({ num }, o) => console.log(`from ${o.num} to ${num}`), {immediate:true}),
- numChangeWithoutImmediate: ({ num }, o) => console.log(`from ${o.num} to ${num}`),
- },
- lifecycle: {
- // loaded: (dispatch) => dispatch("initState"), // [optional] triggered when module loaded
- // initState: async (moduleState) => {/** async logic */ return{num:666}}, // [optional] allow user load state async
- // initStateDone: (dispatch) => dispatch("addSmallAndBig"), // [optional] call any reducer fn after initState done
- mounted: (dispatch) => dispatch("initState"), // [optional] triggered when the first ins of counter module mounted
- willUnmount: (dispatch) => dispatch("initState") // [optional] triggered when the last ins of counter module unmount
- }
- }
- });
- @register("counter")
- class DemoCls extends React.Component {
- render() {
- // mr is short of moduleReducer, now you can call counter module's all reducer fns by mr
- return <button onClick={this.ctx.mr.add}>{this.state.num}</button>;
- }
- }
- function DemoFn() {
- const { moduleComputed, mr } = useConcent("counter");
- return <button onClick={mr.add}>numx2plusBig: {moduleComputed.numx2plusBig}</button>;
- }
- ```
🎲Eco-lib examples
Use with react router
Details see here react-router-concent,exposehistory,you can call it anywhere in your app to enjoy the imperative navigation jump.
Use with redux-dev-tool
Details see here concent-plugin-redux-devtool,track your state changing history。
Use with plugin-loading
Details see here concent-plugin-loading,control all your reducer function's loading status easily。
___
CDN resource
- cdnjs
https://cdnjs.com/libraries/concent
- cdn.bytedance
https://cdn.bytedance.com/?query=concent
- jsdelivr
https://www.jsdelivr.com/package/npm/concent
- unpkg
https://unpkg.com/concent
🐚Who is using it
tcb-admin | wink |
Communication
👅License
concent is released under the MIT License. http://www.opensource.org/licenses/mit-license