Skip to content

Commit

Permalink
feat!: remove useDefined hook
Browse files Browse the repository at this point in the history
  • Loading branch information
geekact committed Sep 8, 2023
1 parent fdabe53 commit c4e070f
Show file tree
Hide file tree
Showing 13 changed files with 22 additions and 474 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v3

- 删除hooks `useDefined`

## [2.0.1](https://github.com/foca-js/foca/compare/v2.0.0...v2.0.1)  (2023-08-10)

- react-redux 版本从 8.1.1 升级到 8.1.2 (#40)
Expand Down
37 changes: 0 additions & 37 deletions docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,43 +37,6 @@ const user3Model = cloneModel('users3', userModel, (prev) => {
});
```

# 局部模型

通过`defineModel``cloneModel`创建的模型均为全局类别的模型,数据一直保持在内存中,直到应用关闭或者退出才会释放,对于比较大的项目,这可能会有性能问题。所以有时候你其实想要一种`用完就扔`的模型,即在 React 组件初始化时把模型数据扔到 store 中,当 React 组件被销毁时,模型的数据也跟着销毁。现在局部模型很适合你的需求:

```tsx
import { useEffect } from 'react';
import { defineModel, useDefined } from 'foca';

// test.model.ts
export const testModel = defineModel('test', {
initialState: { count: 0 },
reducers: {
plus(state, value: number) {
state.count += value;
},
},
});

// App.tsx
const App: FC = () => {
const model = useDefined(testModel);
const { count } = useModel(model);

useEffect(() => {
model.plus(1);
}, []);

return <div>{count}</div>;
};
```

利用 `useDefined` 函数根据全局模型创建一个新的局部模型,然后就是通用的模型操作,这似乎没有增加工作量(因为只多了一行)。下面我列举了局部函数的几个特点:

- 组件内部使用,不污染全局
- 数据随组件自动挂载/释放
- 有效降低内存占用量

# loadings

默认地,methods 函数只会保存一份执行状态,如果你在同一时间多次执行同一个函数,那么状态就会互相覆盖,产生错乱的数据。如果现在有 10 个按钮,点击每个按钮都会执行`model.methodX(id)`,那么我们如何知道是哪个按钮执行的呢?这时候我们需要为执行状态开辟一个独立的存储空间,让同一个函数拥有多个状态互不干扰。
Expand Down
23 changes: 11 additions & 12 deletions docs/api.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
| 方法 | 描述 | 使用频率 | 指南 |
| ----------------- | --------------------------------------- | ----------------------------------- | ------------------------------------- |
| **store.init** | 初始化仓库 | :star2: | [开始使用](/initialize?id=仓库) |
| **store.refresh** | 重置仓库数据 | :star2: | [进阶用法](/advanced?id=重置所有数据) |
| **defineModel** | 创建模型 | :star2::star2::star2::star2::star2: | [模型](/model?id=model) |
| **cloneModel** | 复制模型并允许小量修改 | :star2: | [进阶用法](/advanced?id=克隆模型) |
| **useDefined** | 在 hooks 中创建局部模型,数据随组件释放 | :star2::star2::star2: | [进阶用法](/advanced?id=局部模型) |
| **useModel** | 在 hooks 中使用模型的状态 | :star2::star2::star2::star2::star2: | [数据对接](/react?id=usemodel) |
| **useComputed** | 在 hooks 中使用计算属性 | :star2::star2::star2: | [数据对接](/react?id=usecomputed) |
| **useLoading** | 在 hooks 中获取异步函数的执行状态 | :star2::star2::star2::star2::star2: | [数据对接](/react?id=useloading) |
| **getLoading** | 获取异步函数的当前执行状态 | :star2: | [通用属性](/model?id=loading) |
| **connect** | 在 class 组件中连接 react 和 redux | :star2: | [数据对接](/react?id=connect) |
| 方法 | 描述 | 使用频率 | 指南 |
| ----------------- | ---------------------------------- | ----------------------------------- | ------------------------------------- |
| **store.init** | 初始化仓库 | :star2: | [开始使用](/initialize?id=仓库) |
| **store.refresh** | 重置仓库数据 | :star2: | [进阶用法](/advanced?id=重置所有数据) |
| **defineModel** | 创建模型 | :star2::star2::star2::star2::star2: | [模型](/model?id=model) |
| **cloneModel** | 复制模型并允许小量修改 | :star2: | [进阶用法](/advanced?id=克隆模型) |
| **useModel** | 在 hooks 中使用模型的状态 | :star2::star2::star2::star2::star2: | [数据对接](/react?id=usemodel) |
| **useComputed** | 在 hooks 中使用计算属性 | :star2::star2::star2: | [数据对接](/react?id=usecomputed) |
| **useLoading** | 在 hooks 中获取异步函数的执行状态 | :star2::star2::star2::star2::star2: | [数据对接](/react?id=useloading) |
| **getLoading** | 获取异步函数的当前执行状态 | :star2: | [通用属性](/model?id=loading) |
| **connect** | 在 class 组件中连接 react 和 redux | :star2: | [数据对接](/react?id=connect) |
21 changes: 0 additions & 21 deletions docs/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,3 @@ export const testModel = defineModel('test', {
},
});
```

## onDestroy

模型数据从 store 卸载时的回调通知。onDestroy 事件只针对`局部模型`,即通过`useDefined`这个 hooks api 创建的模型才会触发,因为局部模型是跟随组件一起创建和销毁的。

注意,当触发 onDestroy 回调时,模型已经被卸载了,所以无法再拿到当前数据,而且`this`上下文也被限制使用了。

```typescript
import { defineModel } from 'foca';

const initialState = { count: 0 };

export const testModel = defineModel('test', {
initialState,
events: {
onDestroy() {
console.log('Destroyed');
},
},
});
```
4 changes: 2 additions & 2 deletions docs/mindMap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export { useLoading } from './api/useLoading';
export { getLoading } from './api/getLoading';
export { connect } from './redux/connect';
export { useComputed } from './reactive/useComputed';
export { useDefined } from './model/useDefined';

// 入口使用
export { compose } from 'redux';
Expand All @@ -27,6 +26,6 @@ export type {
StoreEnhancer,
Unsubscribe,
} from 'redux';
export type { Model, HookModel } from './model/types';
export type { Model } from './model/types';
export type { StorageEngine } from './engines';
export type { ComputedRef } from './reactive/types';
15 changes: 1 addition & 14 deletions src/model/defineModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export const defineModel = <
}

if (events) {
const { onInit, onChange, onDestroy } = events;
const { onInit, onChange } = events;
const eventCtx: EventCtx<State> = Object.assign(
composeGetter({ name: uniqueName }, getState),
enhancedMethods.external,
Expand All @@ -233,19 +233,6 @@ export const defineModel = <
);
}

if (onDestroy) {
subscriptions.push(
modelStore.subscribe(() => {
if (eventCtx.state === void 0) {
for (let i = 0; i < subscriptions.length; ++i) {
subscriptions[i]!();
}
onDestroy.call(null as never);
}
}),
);
}

if (onInit) {
/**
* 初始化时,用到它的React组件可能还没加载,所以执行async-method时无法判断是否需要保存loading。因此需要一个钩子来处理事件周期
Expand Down
30 changes: 0 additions & 30 deletions src/model/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,37 +126,13 @@ type ModelComputed<Computed extends object> = {
: never;
};

class ModelIdentity {
private declare readonly _global: true;
}

export type Model<
Name extends string = string,
State extends object = object,
Action extends object = object,
Effect extends object = object,
Computed extends object = object,
> = BaseModel<Name, State> &
ModelIdentity &
// [K in keyof Action as K extends `_${string}` ? never : K]
// 上面这种看起来简洁,业务代码提示也正常,但是业务代码那边无法点击跳转进模型了。
// 所以需要先转换所有的属性,再把私有属性去除。
Omit<ModelAction<State, Action>, GetPrivateMethodKeys<Action>> &
Omit<ModelEffect<Effect>, GetPrivateMethodKeys<Effect>> &
Omit<ModelComputed<Computed>, GetPrivateMethodKeys<Computed>>;

class HookModelIdentity {
private declare readonly _hooks: true;
}

export type HookModel<
Name extends string = string,
State extends object = object,
Action extends object = object,
Effect extends object = object,
Computed extends object = object,
> = BaseModel<Name, State> &
HookModelIdentity &
// [K in keyof Action as K extends `_${string}` ? never : K]
// 上面这种看起来简洁,业务代码提示也正常,但是业务代码那边无法点击跳转进模型了。
// 所以需要先转换所有的属性,再把私有属性去除。
Expand Down Expand Up @@ -193,12 +169,6 @@ export interface Event<State> {
* 上下文 **this** 可以直接调用actions和effects的函数以及computed计算属性,请谨慎执行修改数据的操作以防止死循环。
*/
onChange?: (prevState: State, nextState: State) => void;
/**
* 销毁模型时的回调通知,此时模型已经被销毁。
* 该事件仅在局部模型生效
* @see useDefined
*/
onDestroy?: (this: never) => void;
}

export interface EventCtx<State extends object>
Expand Down
111 changes: 0 additions & 111 deletions src/model/useDefined.ts

This file was deleted.

6 changes: 3 additions & 3 deletions src/model/useModel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { shallowEqual } from 'react-redux';
import { deepEqual } from '../utils/deepEqual';
import type { HookModel, Model } from './types';
import type { Model } from './types';
import { toArgs } from '../utils/toArgs';
import { useModelSelector } from '../redux/useSelector';
import { isFunction, isString } from '../utils/isType';
Expand All @@ -21,10 +21,10 @@ export type Algorithm = 'strictEqual' | 'shallowEqual' | 'deepEqual';
* * 最后一个参数如果是**函数**,则为状态过滤函数,过滤函数的结果视为最终返回值。
*/
export function useModel<State extends object>(
model: Model<string, State> | HookModel<string, State>,
model: Model<string, State>,
): State;
export function useModel<State extends object, T>(
model: Model<string, State> | HookModel<string, State>,
model: Model<string, State>,
selector: (state: State) => T,
algorithm?: Algorithm,
): T;
Expand Down
Loading

0 comments on commit c4e070f

Please sign in to comment.