/rectx

a light-weight state manager.

Primary LanguageJavaScriptMIT LicenseMIT

Rectx

NPM version build status Test coverage David deps node version npm download

a light-weight state manager with mutable api.

安装

npm install --save rectx

又一个轮子?

ReduxMobx 都非常的棒,但对于大部分项目都只是 CRUD 的项目来说,这些个玩意儿都略显太重了。而且对于 react 的 immutable 哲学而言,实在是模版代码相当的多,对新手、高手、熟练工都不是很友好:新手觉得复杂,高手觉得烦躁,熟练工觉得不够快。再加上,react 函数式编程以及 DOM-diff 依赖的是 html tag 的缘故,因此我们需要手动优化,臭名昭著的 shouldComponentUpdate 由此而来。

为了更好的解决上述的一些问题,我开始寻找一种方式能够解决:

  1. 模版化很少
  2. 无需手动 shouldComponentUpdate
  3. API 极少,学习成本低
  4. mutable API

以下就是我的解决方案。

特点

rectx 有着强大的功能,他不仅能提供一个状态库,甚至能提供一个良好的类型辅助系统,这也意味着你可以在 TypeScript 中支持它!

  • 并不依赖 react.context api,支持 15、16 版本的 react
  • mutable api,再也不用写模版代码
  • 完整的测试,测试覆盖率极高
  • typescriptd.ts 支持,非常友好的类型提示
  • 不用写 shouldComponentUpdate 的组件 Auto(自动)
  • 高性能,轻量

最简单的使用

当然了,这个例子如果你看就懂,那我非常建议你直接去看我是如何处理,使得不需要写 shouldComponentUpdatecode sandbox 例子

import React from 'react';
import {render} from 'react-dom';
import {init} from 'rectx';

const {Put, Ctx} = init({foo: 1});

const App = () => (
  <div>
    <Ctx>{s => <div>{s.foo}</div>}</Ctx>
    <button onClick={() => Put(s => (s.foo = s.foo + 1))}>add</button>
  </div>
);

render(<App />, document.getElementById('root'));

值得注意的是,Put(s => (s.foo = s.foo + 1)) 在这里,我们直接修改了我们的数值,当数据非常复杂的时候,这种操作方式尤为珍贵。

无需 shouldComponentUpdate 的组件 Auto

code sandbox 例子

import { init } from "rectx";

const { Put, Ctx, Auto } = init({ foo: 1, bar: 1 });

首先我们依然是引入我们的组件,Put 用于更新,Ctx 用于获取,那么 Auto 是一个什么鬼?

Auto 是一个选择器,他能够分离我们的 Store ,把每一个 Store 切分成一个小粒度的,使得我们的代码更加简洁。比如我们想获取全局状态 store 中的,bar,我们就可以:

const Bars = Auto(s => s.bar);

当我们使用 Bars 的时候,我们获取到的就是 bar 这个属性了。当然,Auto 翻译为自动,这是他第一个自动的地方,第二个特点请看下面:

import React from "react";
import { render } from "react-dom";
import { init } from "rectx";

const { Put, Ctx, Auto } = init({ foo: 1, bar: 1 });

const Bars = Auto(s => s.bar);

const App = () => (
  <div>
    <Ctx>{s => <div>Foo:{s.foo}</div>}</Ctx>
    {Bars(bar => <div>Bar:{bar}</div>)}
    <button onClick={() => Put(s => (s.foo = s.foo + 1))}>change Foo</button>
    <button onClick={() => Put(s => (s.bar = s.bar + 1))}>change Bar</button>
  </div>
);

render(<App />, document.getElementById("root"));

首先 Auto 是一个 selector,其作用是获取全局的状态,从中选出 你关心的 属性,当这些属性被选择出来以后,只要这些属性没有被更新,那么他们所返回的组件 一定不会 更新。同时,外部的属性是否更新,跟他们同样没有任何关系。

熟悉 React 的同学,一定知道这么做的珍贵之处,再也不用手动书写 shouldComponentUpdate 了。

读取全局状态 Store

有时候,有的同学想读取全局的 Store ,我特意提供了一个 API,给大家这么做,特别注意的是这个API 是只读的

import React from "react";
import { render } from "react-dom";
import { init } from "rectx";

const { Put, Ctx, Auto,Store } = init({ foo: 1, bar: 1 });


console.log(Store());//  { foo: 1, bar: 1 }

Put(state => state.foo = 2);

console.log(Store());//  { foo: 2, bar: 1 }

类型提示

得益于 typescriptRectx 得到了良好的类型提示。

当我们初始化 store 以后,我们的 store 里面具体有什么值,在纯 js 中并没有智能提示,但加入了 ts 之后,一切会大不一样

开源协议

MIT