English | 简体中文
concent
Definitely the ❤️ simplest but ⚡️ strongest state management for react, it is predictable、progressive and efficient.
✨Features
- 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
- Module clone support
- Reducer combination support
- Event system support
- Middleware and plugin is support
- React Devtools support
- Hot-reload support
- Compatible with Redux ecology
- SSR&Nextjs support
- React-native support
- Very friendly typeScript support
Docs
visit official website https://concentjs.github.io/concent-doc to learn more.
📦Quick start
Make sure you have installed nodejs。
Install
$ npm i --save concent
or yarn command
$ yarn add concent
Minimal example
import { run } from 'concent';
import { register, useConcent } from 'concent';
run({
counter: {// declare a moudle named 'counter'
state: { num: 1, numBig: 100 }, // define state
},
// you can also put another module here.
});
@register('counter')
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');
const inc = ()=> setState({num: state.num + 1});
return <button onClick={inc}>{state.num}</button>
}
export default function App(){
return (
<div>
<ClsComp />
<FnComp />
</div>
);
}
Complete examples
- Move logic to
reducer
and definecomputed
、watch
、lifecycle
try edit this demo、 👉better js demo、👉better ts demo
import { run, 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) => {
await ac.dispatch("add"); // hate string literal? see https://codesandbox.io/s/combine-reducers-better-7u3t9
await ac.dispatch("addBig");
}
},
watch: {
numChange: defWatch(({ num }, o) => console.log(`from ${o.num} to ${num}`), {immediate:true})
},
lifecycle: {
// loaded: (dispatch) => dispatch("initState"), // when module loaded
mounted: (dispatch) => dispatch("initState"), // when any first ins of counter module mounted will trigger this
willUnmount: (dispatch) => dispatch("initState") // when last ins of counter module unmount will trigger this
}
}
});
@register("counter")
class DemoCls extends React.Component {
render() {
// mr is short of moduleReducer, now you can call all counter module 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>;
}
💻 Playground
Key features snippet
- Dep collection of state
- Dep collection of computed
- Combine reducers
- Composition api
- Ref lifecycle method
- Flexible top api
Real world
- A standard js project with concent-eco lib
- A standard ts project with concent-eco lib
- Todo-mvc-concent vs Todo-mvc-redux
- Calculator-concent vs Calculator-hook
- Concent query list & Concent Shared query list vs Hook query list
- Concent-nextjs-ssr
Eco system
With middleware and plugin mechanism, you can easily cutomize your common handler for non logic code, or migrate redux
eco lib.
Use with react router
Details see here react-router-concent,expose history
,you can call it anywhere in your app to enjoy the imperative navigation jump.
react-router-concent online demo
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。
concent-plugin-loading online demo
📰 Articles
- redux、mobx、concent特性大比拼, 看后生如何对局前辈
- 聊一聊状态管理&Concent设计理念
- 应战Vue3 setup,Concent携手React出招了!
- 深度挖掘Concent的effect,全面提升useEffect的开发体验
- concent *操作之组件创建&状态更新
- 使用concent,体验一把渐进式地重构react应用之旅