关于redux:新的React状态库foca

基于 redux 和 react-redux。仓库地址:https://github.com/foca-js/foca

理念

TS First,无TS不编程!

个性

  • 模块化开发
  • 专一 typescript 极致体验
  • 模型主动注册,导出即可应用
  • 内置 immer 疾速解决数据
  • 智能追踪异步函数的执行状态
  • 模型反对公有办法
  • 可定制的多引擎数据长久化
  • 数据隔离,容许同类状态库并存

架构图

在线试玩

CodeSandBox

应用

定义模型

// File: counterModel.ts
import { defineModel } from 'foca';

const initialState: { count: number } = {
  count: 0,
};

// 毋庸手动注册到store,间接导出到react组件中应用
export const counterModel = defineModel('counter', {
  // 初始值,必填属性,其余属性均可选
  initialState,
  actions: {
    // state可主动提醒类型 { count: number }
    plus(state, value: number, double: boolean = false) {
      // 间接批改状态
      state.count += value * (double ? 2 : 1);
    },
    minus(state, value: number) {
      // 间接返回新状态
      return { count: state.count - value };
    },
    // 公有办法,只能在模型外部被effect办法调用,内部调用则TS报错(属性不存在)
    _clear(state) {
      return this.initialState;
    },
  },
  effects: {
    // 异步函数,主动追踪执行状态(loading)
    async doSomething() {
      // 调用公有办法
      await this._sleep(100);

      // 疾速解决状态,对于网络申请的数据非常不便
      this.setState({ count: 1 });
      this.setState((state) => {
        state.count += 1;
      });
      // 调用action函数解决状态
      this.plus(1, true);

      // 调用effect函数
      return this.commonUtil(1);
    },
    // 一般函数
    commonUtil(x: number) {
      return x + 1;
    },
    // 公有办法,只能在模型外部应用,内部调用则TS报错(属性不存在)
    _sleep(duration: number) {
      return new Promise((resolve) => {
        setTimeout(resolve, duration);
      });
    },
  },
  hooks: {
    // store初始化实现后触发onInit钩子
    onInit() {
      this.plus(1);
      console.log(this.state);
    },
  },
});

在函数组件中应用

import { FC, useEffect } from 'react';
import { useModel, useLoading } from 'foca';
import { counterModel } from './counterModel';

const App: FC = () => {
  // count类型主动提醒 number
  const { count } = useModel(counterModel);
  // 仅effects的异步函数能作为参数传入,其余函数TS主动报错
  const loading = useLoading(counterModel.doSomething);

  useEffect(() => {
    counterModel.doSomething();
  }, []);

  return (
    <div onClick={() => counterModel.plus(1)}>
      {count} {loading ? 'Loading...' : null}
    </div>
  );
};

export default App;

在类组件中应用

import { Component } from 'react';
import { connect, getLoading } from 'foca';
import { counterModel } from './counterModel';

type Props = ReturnType<typeof mapStateToProps>;

class App extends Component<Props> {
  componentDidMount() {
    counterModel.doSomething();
  }

  render() {
    const { count, loading } = this.props;

    return (
      <div onClick={() => counterModel.plus(1)}>
        {count} {loading ? 'Loading...' : null}
      </div>
    );
  }
};

const mapStateToProps = () => {
  return {
    count: counterModel.state.count,
    loading: getLoading(counterModel.doSomething);
  };
}

export default connect(mapStateToProps)(App);

心愿能成为你下一个我的项目的状态治理计划!喜爱就先star一下吧。
仓库地址:https://github.com/foca-js/foca

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理