之前一直写vue,在vue2里面有vue.observable, 在vue3里面有pinia, 用起来都是极简的, 今年转react感觉状态管理都不是很好用,有限配置起来一点都不方便。后面看了ahooks里面的源码,在useReactivehooks里面找到了灵感。就有了现在的react-pinia, 因为这个库是依赖react hooks的,所以只适合react函数组件使用。react-pinia实现了局部状态管理和全局状态管理。
源码就不放出来了,怕被吐槽,原理其实也很简单,有点vue的思想去驱动界面更新
安装
npm i react-pinia -S
全局状态使用
定义全局状态,为了方便我就写在一起了,大家可以分开写
export default {
user: {
username: '',
password: '',
},
article: {
loading: false,
list: [],
},
}
在入口引入状态定义, 全局挂载,类似redux
import { Provider } from 'react-pinia'
import store from '@/store'
export default () => {
return (
<Provider store={store}>
<App />
</Provider>
)
}
在然后page页面使用的时候就直接调用createStore方法就可以了, createStore是如何知道user 或者 article被更新了呢?或者说当前页面只需要知道user的数据被改动了,这里createStore 传当前页面接收的模块状态变化,可以是数组或者字符串,也可以不传,不传就任何模块的数据改动都能接收到,为了性能建议至少传一个。
import { createStore } from 'react-pinia'
export default () => {
const { user } = createStore('user')
return (
<section>
<input
value={user.username}
onChange={(e) => {
user.username = e.target.value
}}
/>
{user.username}
</section>
)
}
局部状态使用
在局部状态中使用就非常简单了,定义的语法有点像pinia, 所以这个库就叫react-pinia, 直接上代码, 这里为了简便就都写在一起了,在这个里面useStore在组件中使用也是一样的可以接收需要监听的数据,不传就是所有
import { defineStore } from 'react-pinia'
// 定义局部状态
const useStore = defineStore('count', {
state: () => {
return {
count: 0,
}
},
getters: {
doubleCount: (state: Record<string, any>) => {
return state.count * 2
},
},
actions: {
add() {
this.count += 1
},
},
})
const Child = () => {
const store = useStore('count')
return <section>{store.count}</section>
}
const App = () => {
const store = useStore()
return (
<section>
<p>count: {store.count}</p>
<p>doubleCount: {store.doubleCount}</p>
<button onClick={store.add}>add</button>
<Child />
</section>
)
}