3

新的React状态库:foca

 2 years ago
source link: https://segmentfault.com/a/1190000041166881
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

新的React状态库:foca

发布于 今天 03:58
English

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

TS First,无TS不编程!

  • 模块化开发
  • 专注 typescript 极致体验
  • 模型自动注册,导出即可使用
  • 内置 immer 快速处理数据
  • 智能追踪异步函数的执行状态
  • 模型支持私有方法
  • 可定制的多引擎数据持久化
  • 数据隔离,允许同类状态库并存

image.png

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK