rekv
v1.2.2
Published
Rekv 是一个为 React 函数式组件设计的全局状态管理器,且对类组件具有很好的兼容,所有方法与状态均有 TypeScript 提示
Downloads
152
Maintainers
Readme
Rekv
Rekv 是一个为 React 函数式组件设计的全局状态管理器,且对类组件具有很好的兼容,所有方法与状态均有 TypeScript 提示
特色
- 一个简单但易用的状态管理器
- 高性能,使用 Key-Value 而不是树型结构来处理状态
- 支持 TypeScript 静态检查
- 支持状态变更事件委托(拦截器)
- 无 Redux,无依赖,仅 state
- 不使用高阶组件(HOC)
目录
Demo
- 预览地址: https://csb-s8sbu.netlify.app/
- 在线编辑: https://codesandbox.io/s/strange-antonelli-s8sbu
安装方式
yarn add rekv
版本要求:React 版本 >= 16.8.0
快速使用
适用于小型项目,只需要一个全局状态
// Demo.tsx
import React from 'react';
import { globalStore } from 'rekv';
export default function Demo() {
// 使用状态
const { name } = globalStore.useState('name');
return <div>Hello, {name}</div>;
}
// 在另一个文件,或其他地方调用
globalStore.setState({ name: 'Jack' });
API
class Rekv
new Rekv(object)
创建一个
Rekv
的实例delegate
全局事件委托全局事件委托,可设置所有
Rekv
实例的事件委托beforeUpdate
状态更新前的事件,可对设置的状态进行拦截,检查并修改import Rekv from 'rekv'; // 所有 `Rekv` 的实例,在更新前都将执行此方法 // state: 使用 setState() 更新的状态值 // store: 需要更新状态的 store // 返回值: 如果需要拦截并修改 setState 的值,可返回一个新的对象,替换 setState 的值 Rekv.delegate.beforeUpdate = ({ state, store }) => { console.log(store.currentState, state); // return state; // 可选,如果返回了新的值,则可实现对状态的拦截修改 };
afterUpdate
状态更新后的事件,返回已更新的状态import Rekv from 'rekv'; // 所有的 `Rekv` 实例,在完成状态更新后,执行此方法 // state: 已更新的状态(这里已过滤掉未发生改变的状态) // store: 已更新状态的 store Rekv.delegate.afterUpdate = ({ state, store }) => { console.log(store.currentState, state); };
globalStore
globalStore 是一个默认创建的
Rekv
类的实例,可使用Rekv
实例的所有方法与属性Rekv 实例属性与方法
.delegate
使用方式与 全局事件委托 相同实例的事件委托,如果和全局的事件委托同时设置了,会优先执行实例的事件委托,再执行全局的事件委托,使用方式用全局事件委托相同
.currentState
获取当前时刻实例的状态.getCurrentState()
与.currentState
功能相同.useState()
在函数式组件中订阅并使用状态,通过设置多个参数,可在一行使用多个状态
import React from 'react'; import store from './store'; function Demo() { const s = store.useState('foo', 'bar'); return ( <div> {s.foo}, {s.bar} </div> ); }
.setState()
对状态进行更新import store from './store'; // 方法1: 直接设置状态 store.setState({ count: 1 }); // 方法2: 使用一个回调函数,获取当前状态,并返回新的状态 // state: 当前状态 store.setState((state) => { return { count: state.count + 1, }; });
.classUseState()
在类组件中使用状态
高级用法
适用于多个 Store 的情况,可对每个状态进行 TypeScript 静态检查
函数式组件使用方式
使用 Rekv 创建一个 store
// store.ts
import Rekv from 'rekv';
export default new Rekv({
name: 'test',
count: 0,
});
使用状态
import React from 'react';
import store from './store';
export default function Demo() {
const { name, count } = store.useState('name', 'count');
return (
<div>
{name}, {count}
</div>
);
}
在另一个组件内更新状态
import React from 'react';
import store from './store';
// 重置计数器
function reset() {
store.setState({ count: 0 });
}
function increment() {
store.setState((state) => ({ count: state.count + 1 }));
}
function decrement() {
store.setState((state) => ({ count: state.count - 1 }));
}
export default function Buttons() {
return (
<div>
<button onClick={reset}>reset</button>
<button onClick={increment}>+1</button>
<button onClick={decrement}>-1</button>
</div>
);
}
在类组件中使用
import React, { Component } from 'react';
import store from './store';
export default class MyComponent extends Component {
s = store.classUseState(this, 'count');
render() {
return <div>{this.s.count}</div>;
}
}
使用 TypeScript 类型检查
// store.ts
import Rekv from 'rekv';
interface InitState {
name: string;
age?: number;
}
const initState: InitState = {
name: 'Jack',
age: 25,
};
const store = new Rekv(initState);
export default store;
// User.ts
import React from 'react';
import store from './store';
export default function User() {
// name 将被推断为 string 类型
// age 将被推断为 number | undefined 类型
const { name, age } = store.useState('name', 'age');
return (
<div>
{name}, {age}
</div>
);
}
获取当前时刻的状态
import store from './store';
// 获取当前时刻的状态
store.currentState;
// 或
store.getCurrentState(); // 兼容旧版本的 API
事件委托、拦截器
import store from './store';
store.delegate = {
beforeUpdate: ({ state }) => {
console.log('beforeUpdate', state);
// 可在这里拦截 setState 的值,并进行修改
return state;
},
afterUpdate: ({ state }) => {
// afterUpdate 的 state 只包含了需要更新的状态
console.log('afterUpdate', state);
},
};
使用副作用
import Rekv froom 'rekv';
// 定义副使用
const store = new Rekv(
{ foo: 'bar' },
{
effects: {
changeFoo(name: string) {
this.setState({ foo: name });
},
},
}
);
// 使用副作用
store.effects.changeFoo('hello')