{"id":13459610,"url":"https://github.com/foca-js/foca","last_synced_at":"2025-03-24T18:30:59.676Z","repository":{"id":37084020,"uuid":"421430558","full_name":"foca-js/foca","owner":"foca-js","description":"流畅的React状态管理库","archived":false,"fork":false,"pushed_at":"2024-07-21T17:20:14.000Z","size":2791,"stargazers_count":261,"open_issues_count":9,"forks_count":30,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-10-29T01:14:03.716Z","etag":null,"topics":["react-redux","react-state-management","redux","redux-model","redux-toolkit","redux-typescript"],"latest_commit_sha":null,"homepage":"http://foca.js.org","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/foca-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-26T13:12:54.000Z","updated_at":"2024-10-15T08:37:25.000Z","dependencies_parsed_at":"2023-09-27T23:28:18.683Z","dependency_job_id":"2aea3c29-91c3-4289-bf8e-42017f21656b","html_url":"https://github.com/foca-js/foca","commit_stats":{"total_commits":532,"total_committers":5,"mean_commits":106.4,"dds":"0.48120300751879697","last_synced_commit":"bc11584c427da558895faebef5106fd311723fc3"},"previous_names":[],"tags_count":61,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca-js%2Ffoca","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca-js%2Ffoca/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca-js%2Ffoca/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foca-js%2Ffoca/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foca-js","download_url":"https://codeload.github.com/foca-js/foca/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221995732,"owners_count":16913552,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["react-redux","react-state-management","redux","redux-model","redux-toolkit","redux-typescript"],"created_at":"2024-07-31T10:00:22.573Z","updated_at":"2025-03-24T18:30:59.667Z","avatar_url":"https://github.com/foca-js.png","language":"TypeScript","funding_links":[],"categories":["语言资源库"],"sub_categories":["typescript"],"readme":"# FOCA\n\n流畅的 react 状态管理库，基于[redux](https://github.com/reduxjs/redux)和[react-redux](https://github.com/reduxjs/react-redux)。简洁、极致、高效。\n\n[![npm peer react version](https://img.shields.io/npm/dependency-version/foca/peer/react?logo=react)](https://github.com/facebook/react)\n[![npm peer typescript version](https://img.shields.io/npm/dependency-version/foca/peer/typescript?logo=typescript)](https://github.com/microsoft/TypeScript)\n[![GitHub Workflow Status (branch)](https://img.shields.io/github/actions/workflow/status/foca-js/foca/test.yml?branch=master\u0026label=test\u0026logo=vitest)](https://github.com/foca-js/foca/actions)\n[![Codecov](https://img.shields.io/codecov/c/github/foca-js/foca?logo=codecov)](https://codecov.io/gh/foca-js/foca)\n[![npm](https://img.shields.io/npm/v/foca?logo=npm)](https://www.npmjs.com/package/foca)\n[![npm](https://img.shields.io/npm/dt/foca?logo=codeforces)](https://www.npmjs.com/package/foca)\n[![npm bundle size (version)](https://img.shields.io/bundlephobia/minzip/foca?label=bundle+size\u0026cacheSeconds=3600\u0026logo=esbuild)](https://bundlephobia.com/package/foca@latest)\n[![License](https://img.shields.io/github/license/foca-js/foca?logo=open-source-initiative)](https://github.com/foca-js/foca/blob/master/LICENSE)\n[![Code Style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?logo=prettier)](https://github.com/prettier/prettier)\n\n\u003cbr\u003e\n\n![mind map](https://raw.githubusercontent.com/foca-js/foca/master/docs/mindMap.svg)\n\n# 特性\n\n- 模块化开发，导出即可使用\n- 专注 TS 极致体验，超强的类型自动推导\n- 内置 [immer](https://github.com/immerjs/immer) 响应式修改数据\n- 支持计算属性，自动收集依赖，可传参数\n- 自动管理异步函数的 loading 状态\n- 可定制的多引擎数据持久化\n- 支持局部模型，用完即扔\n- 支持私有方法\n\n# 使用环境\n\n- Browser\n- React Native\n- Taro\n- Electron\n\n# 安装\n\n```bash\n# npm\nnpm install foca\n# yarn\nyarn add foca\n# pnpm\npnpm add foca\n```\n\n# 初始化\n\n```typescript\nimport { store } from 'foca';\n\nstore.init();\n```\n\n# 创建模型\n\n### reducers 修改数据\n\n```typescript\nimport { defineModel } from 'foca';\n\nconst initialState: { count: number } = { count: 0 };\n\nexport const counterModel = defineModel('counter', {\n  initialState,\n  reducers: {\n    // 支持无限参数\n    plus(state, value: number, times: number = 1) {\n      state.count += value * times;\n    },\n    minus(state, value: number) {\n      return { count: state.count - value };\n    },\n  },\n});\n```\n\n### computed 计算属性\n\n```typescript\nexport const counterModel = defineModel('counter', {\n  initialState,\n  // 自动收集依赖\n  computed: {\n    filled() {\n      return Array(this.state.count)\n        .fill('')\n        .map((_, index) =\u003e index)\n        .map((item) =\u003e item * 2);\n    },\n  },\n});\n```\n\n### methods 组合逻辑\n\n```typescript\nexport const counterModel = defineModel('counter', {\n  initialState,\n  reducers: {\n    increment(state) {\n      state.count += 1;\n    },\n  },\n  methods: {\n    async incrementAsync() {\n      await this._sleep(100);\n\n      this.increment();\n      // 也可直接修改状态而不通过reducers，仅在内部使用\n      this.setState({ count: this.state.count + 1 });\n      this.setState((state) =\u003e {\n        state.count += 1;\n      });\n\n      return 'OK';\n    },\n    // 私有方法，外部使用时不会提示该方法\n    _sleep(duration: number) {\n      return new Promise((resolve) =\u003e {\n        setTimeout(resolve, duration);\n      });\n    },\n  },\n});\n```\n\n### events 事件回调\n\n```typescript\nexport const counterModel = defineModel('counter', {\n  initialState,\n  events: {\n    // 模型初始化\n    onInit() {\n      console.log(this.state);\n    },\n    // 模型数据变更\n    onChange(prevState, nextState) {},\n  },\n});\n```\n\n# 使用\n\n### 在 function 组件中使用\n\n```tsx\nimport { FC, useEffect } from 'react';\nimport { useModel, useLoading } from 'foca';\nimport { counterModel } from './counterModel';\n\nconst App: FC = () =\u003e {\n  const count = useModel(counterModel, (state) =\u003e state.count);\n  const loading = useLoading(counterModel.incrementAsync);\n\n  useEffect(() =\u003e {\n    counterModel.incrementAsync();\n  }, []);\n\n  return (\n    \u003cdiv onClick={() =\u003e counterModel.plus(1)}\u003e\n      {count} {loading ? 'Loading...' : null}\n    \u003c/div\u003e\n  );\n};\n\nexport default App;\n```\n\n### 在 class 组件中使用\n\n```tsx\nimport { Component } from 'react';\nimport { connect, getLoading } from 'foca';\nimport { counterModel } from './counterModel';\n\ntype Props = ReturnType\u003ctypeof mapStateToProps\u003e;\n\nclass App extends Component\u003cProps\u003e {\n  componentDidMount() {\n    counterModel.incrementAsync();\n  }\n\n  render() {\n    const { count, loading } = this.props;\n\n    return (\n      \u003cdiv onClick={() =\u003e counterModel.plus(1)}\u003e\n        {count} {loading ? 'Loading...' : null}\n      \u003c/div\u003e\n    );\n  }\n}\n\nconst mapStateToProps = () =\u003e {\n  return {\n    count: counterModel.state.count,\n    loading: getLoading(counterModel.incrementAsync),\n  };\n};\n\nexport default connect(mapStateToProps)(App);\n```\n\n# 文档\n\nhttps://foca.js.org\n\n# 例子\n\n沙盒在线试玩：https://codesandbox.io/s/foca-demos-e8rh3\n\u003cbr /\u003e\nReact 案例仓库：https://github.com/foca-js/foca-demo-web\n\u003cbr\u003e\nRN 案例仓库：https://github.com/foca-js/foca-demo-react-native\n\u003cbr\u003e\nTaro 案例仓库：https://github.com/foca-js/foca-demo-taro\n\n# 生态\n\n#### 网络请求\n\n| 仓库                                                    | 版本                                                                                            | 描述                          |\n| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------- |\n| [axios](https://github.com/axios/axios)                 | [![npm](https://img.shields.io/npm/v/axios)](https://www.npmjs.com/package/axios)               | 当下最流行的请求库            |\n| [foca-axios](https://github.com/foca-js/foca-axios)     | [![npm](https://img.shields.io/npm/v/foca-axios)](https://www.npmjs.com/package/foca-axios)     | axios++ 支持 节流、缓存、重试 |\n| [foca-openapi](https://github.com/foca-js/foca-openapi) | [![npm](https://img.shields.io/npm/v/foca-openapi)](https://www.npmjs.com/package/foca-openapi) | 使用openapi文档生成请求服务   |\n\n#### 持久化存储引擎\n\n| 仓库                                                                                      | 版本                                                                                                                                                      | 描述                                       | 平台     |\n| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -------- |\n| [react-native-async-storage](https://github.com/react-native-async-storage/async-storage) | [![npm](https://img.shields.io/npm/v/@react-native-async-storage/async-storage)](https://www.npmjs.com/package/@react-native-async-storage/async-storage) | React-Native 持久化引擎                    | RN       |\n| [foca-taro-storage](https://github.com/foca-js/foca-taro-storage)                         | [![npm](https://img.shields.io/npm/v/foca-taro-storage)](https://www.npmjs.com/package/foca-taro-storage)                                                 | Taro 持久化引擎                            | Taro     |\n| [localforage](https://github.com/localForage/localForage)                                 | [![npm](https://img.shields.io/npm/v/localforage)](https://www.npmjs.com/package/localforage)                                                             | 浏览器端持久化引擎，支持 IndexedDB, WebSQL | Web      |\n| [foca-electron-storage](https://github.com/foca-js/foca-electron-storage)                 | [![npm](https://img.shields.io/npm/v/foca-electron-storage)](https://www.npmjs.com/package/foca-electron-storage)                                         | Electron 持久化引擎                        | Electron |\n| [foca-mmkv-storage](https://github.com/foca-js/foca-mmkv-storage)                         | [![npm](https://img.shields.io/npm/v/foca-mmkv-storage)](https://www.npmjs.com/package/foca-mmkv-storage)                                                 | 基于 mmkv 的持久化引擎                     | RN       |\n| [foca-cookie-storage](https://github.com/foca-js/foca-cookie-storage)                     | [![npm](https://img.shields.io/npm/v/foca-cookie-storage)](https://www.npmjs.com/package/foca-cookie-storage)                                             | Cookie 持久化引擎                          | Web      |\n\n#### 日志\n\n| 仓库                                                                       | 版本                                                                                                                      | 描述           | 平台          |\n| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------- | ------------- |\n| [@redux-devtools/extension](https://github.com/reduxjs/redux-devtools)     | [![npm](https://img.shields.io/npm/v/@redux-devtools/extension)](https://www.npmjs.com/package/@redux-devtools/extension) | 浏览器日志插件 | Web, RN       |\n| [react-native-debugger](https://github.com/jhen0409/react-native-debugger) | [![npm](https://img.shields.io/npm/v/react-native-debugger)](https://www.npmjs.com/package/react-native-debugger)         | 日志应用程序   | RN            |\n| [redux-logger](https://github.com/LogRocket/redux-logger)                  | [![npm](https://img.shields.io/npm/v/redux-logger)](https://www.npmjs.com/package/redux-logger)                           | 控制台输出日志 | Web, RN, Taro |\n\n# 常见疑问\n\n### 函数里 this 的类型是 any\n\n答：需要在文件 **tsconfig.json** 中开启`\"strict\": true`或者`\"noImplicitThis\": true`\n\n---\n\n更多答案请[查看文档](https://foca.js.org/#/troubleshooting)\n\n# 捐赠\n\n开源不易，升级维护框架和解决各种 issue 需要十分多的精力和时间。希望能得到你的支持，让项目处于良性发展的状态。捐赠地址：[二维码](https://foca.js.org#donate)\n\n\u003ctable\u003e\n \u003ctr\u003e\n  \u003ctd align=\"center\"\u003e\n    \u003ca target=\"_blank\" href=\"https://github.com/arcsin1?donate_money=16.66\"\u003e\n      \u003cimg src=\"https://avatars.githubusercontent.com/u/13724222\" width=80 height=80 style=\"border-radius: 100%;\" /\u003e\n    \u003c/a\u003e\u003cbr\u003e\n    \u003ca target=\"_blank\" href=\"https://github.com/arcsin1?donate_money=16.66\"\u003earcsin1\u003c/a\u003e\n  \u003c/td\u003e\n  \u003ctd align=\"center\"\u003e\n    \u003ca target=\"_blank\" href=\"https://github.com/xiongxliu?donate_money=50\"\u003e\n      \u003cimg src=\"https://avatars.githubusercontent.com/u/17661296\" width=80 height=80 style=\"border-radius: 100%;\" /\u003e\n    \u003c/a\u003e\u003cbr\u003e\n    \u003ca target=\"_blank\" href=\"https://github.com/xiongxliu?donate_money=50\"\u003exiongxliu\u003c/a\u003e\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoca-js%2Ffoca","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoca-js%2Ffoca","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoca-js%2Ffoca/lists"}