Skip to content

Commit

Permalink
feat: mrege master
Browse files Browse the repository at this point in the history
  • Loading branch information
fantasticsoul committed May 13, 2024
2 parents 9674673 + d299811 commit 81740d9
Show file tree
Hide file tree
Showing 26 changed files with 297 additions and 45 deletions.
35 changes: 35 additions & 0 deletions docs/docs/api/base/demos/run-watch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* defaultShowCode: true
*/
import { share, watch } from 'helux';

const [priceState, setState] = share({ a: 1, c: 0 });

// 观察整个 priceState 的变化
const ret = watch(
() => {
console.log(`found price changed: [ priceState ]`);
},
() => [priceState],
);

ret.unwatch(); // 取消观察后,watch 不会再被自动触发

function changeState() {
setState(draft => void (draft.a += 100));
}

function run() {
ret.run(); // 人工触发始终有效,和 unwatch 是否执行没关系
}

// for react demo renderer
export default () => (
<div>
<h1>after calling unwatch</h1>
<button type="button" onClick={changeState}>change state will not trigger watch</button>
<br />
<br />
<button type="button" onClick={run}>run will still trigger watch</button>
</div>
);
10 changes: 5 additions & 5 deletions docs/docs/api/base/mutate.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ task 和 fn 同时存在,设定`immediate`为`true`,首次执行 mutate 先
const witness = mutate(state)({
deps: () => [state.a, state.b],
fn: (draft, { input }) => (draft.c = input[0] + input[1] + 1),
task: async ({ input }) => {
task: async ({ draft, input }) => {
draft.c = input[0] + input[1] + 1;
},
immediate: true,
Expand All @@ -129,7 +129,7 @@ const witness = mutate(state)({
```ts
const witness = mutate(state)({
deps: () => [state.a, state.b],
task: async ({ input }) => {
task: async ({ draft, input }) => {
draft.c = input[0] + input[1] + 1;
},
});
Expand All @@ -140,7 +140,7 @@ const witness = mutate(state)({
```ts
const witness = mutate(state)({
deps: () => [state.a, state.b],
task: async ({ input }) => {
task: async ({ draft, input }) => {
draft.c = input[0] + input[1] + 1;
},
immediate: false,
Expand Down Expand Up @@ -179,7 +179,7 @@ const [state] = share({ a: 1, b: 1, c: 0 });

const witness = mutate(state)({
deps: () => [state.a, state.b], // deps 返回结果会透传给 taskFnParams.input 数组
task: async ({ input }) => {
task: async ({ draft, input }) => {
draft.c = input[0] + input[1] + 1;
},
});
Expand All @@ -200,7 +200,7 @@ const [state] = share({ a: 1, b: 1, c: 0 });
const witness = mutate(state)({
deps: () => [state.a],
onlyDeps: true,
task: async ({ input }) => {
task: async ({ draft, input }) => {
// 此时 b 的变化不会引起 task 执行
draft.c = input[0] + state.b + 1;
},
Expand Down
4 changes: 4 additions & 0 deletions docs/docs/api/base/watch.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ watch 可观察共享状态跟对象的变化,第二位参数可写为`()=>[]`

<code src="./demos/watch-sub-node.tsx"></code>

### 人工执行/取消watch

<code src="./demos/run-watch.tsx"></code>

## 死循环

设置`immediate`为 true 时,watch 回调首次执行会自动收集依赖,此时如果存在读取自己修改自己的行为,会造成死循环。
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "helux",
"version": "4.2.6",
"version": "4.3.1",
"description": "A reactive atomic state engine for React like.",
"keywords": [],
"author": {
Expand Down
33 changes: 33 additions & 0 deletions packages/helux-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# @helux/core

## 4.3.2

### Patch Changes

- 94cd307: build(4.3.2): optimize delFnDepData
- @helux/hooks-impl@4.3.2
- @helux/types@4.3.2
- @helux/utils@4.3.2

## 4.3.1

### Patch Changes

- 41b9f1d: build(4.3.1): support mutate cancel
- @helux/hooks-impl@4.3.1
- @helux/types@4.3.1
- @helux/utils@4.3.1

## 4.3.0

### Minor Changes

- ac52a46: build(4.2.8): fix unwatch
- 5520458: build(4.2.7): fix unwatch

### Patch Changes

- Updated dependencies [ac52a46]
- Updated dependencies [5520458]
- @helux/hooks-impl@4.3.0
- @helux/types@4.3.0
- @helux/utils@4.3.0

## 4.2.7

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/helux-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@helux/core",
"version": "4.2.7",
"version": "4.3.2",
"description": "A reactive atomic state engine for React like.",
"bugs": {
"url": "https://github.com/heluxjs/helux/issues"
Expand Down
2 changes: 1 addition & 1 deletion packages/helux-core/src/consts/user.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { VER as limuVer } from 'limu';

export const VER = '4.2.7';
export const VER = '4.3.2';

export const LIMU_VER = limuVer;

Expand Down
15 changes: 13 additions & 2 deletions packages/helux-core/src/factory/common/fnScope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,22 @@ export function delComputingFnKey(depKey: string, fnKey: string) {
* 删除已记录的相关依赖数据
*/
export function delFnDepData(fnCtx: IFnCtx) {
const { DEPKEY_FNKEYS_MAP } = getFnScope();
const { depKeys, fnKey } = fnCtx;
const { DEPKEY_FNKEYS_MAP, SKEY_FNKEYS_MAP } = getFnScope();
const { depKeys, fnKey, depSharedKeys } = fnCtx;
const toDel: string[] = [];

depKeys.forEach((key) => {
const fnKeys = DEPKEY_FNKEYS_MAP.get(key) || [];
delListItem(fnKeys, fnKey);
nodupPush(toDel, fnKey);
});

// 将 sharedKey 映射的 fnKey 也一并移除
depSharedKeys.forEach((key) => {
const fnKeysOfSkey = SKEY_FNKEYS_MAP.get(String(key)) || [];
toDel.forEach((key) => {
delListItem(fnKeysOfSkey, key);
});
});
}

Expand Down
27 changes: 20 additions & 7 deletions packages/helux-core/src/factory/createMutate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FROM, SINGLE_MUTATE } from '../consts';
import { delFnDep } from '../helpers/fnDep';
import { getBoundStateInfo, getInternal } from '../helpers/state';
import type {
ActionReturn,
Expand Down Expand Up @@ -48,7 +49,8 @@ function runMutateFnItem<T = SharedState>(options: { target: T; desc?: string; f
return callMutateFnLogic(target, baseOpts);
}

function makeWitness(target: SharedState, desc: string, oriDesc: string, internal: TInternal) {
function makeWitness(target: SharedState, options: { desc: string; oriDesc: string; internal: TInternal; watchFnCtx: any }) {
const { desc, oriDesc, internal, watchFnCtx } = options;
return {
run: (throwErr?: boolean) => {
// 呼叫同步函数的句柄
Expand All @@ -57,6 +59,12 @@ function makeWitness(target: SharedState, desc: string, oriDesc: string, interna
},
// 呼叫异步函数的句柄
runTask: (throwErr?: boolean) => Promise.resolve(runMutateFnItem({ target, desc, forTask: true, throwErr })).then(toMutateRet),
cancel: () => {
// unwatch
delFnDep(watchFnCtx);
// TODO optimize: shuold I use Relect.deleteProperty
delete internal.mutateFnDict[desc];
},
desc,
oriDesc,
getSnap: () => internal.snap,
Expand Down Expand Up @@ -94,14 +102,17 @@ function configureMutateFn(options: IConfigureMutateFnOpt) {
if (extraTarget) {
stdFnItem.extraBound = getBoundStateInfo(extraTarget);
}
const { desc, oriDesc } = stdFnItem;

internal.mutateFnDict[stdFnItem.desc] = stdFnItem;
internal.mutateFnDict[desc] = stdFnItem;
stdFnItem.enabled = internal.enableMutate;
const dict = { [stdFnItem.desc]: stdFnItem };
const dict = { [desc]: stdFnItem };
let watchFnCtx;
if (internal.enableMutate) {
watchAndCallMutateDict({ target, dict });
const retMap = watchAndCallMutateDict({ target, dict });
watchFnCtx = retMap[desc];
}
return makeWitness(target, stdFnItem.desc, stdFnItem.oriDesc, internal);
return makeWitness(target, { desc, oriDesc, internal, watchFnCtx });
}

/**IMutateWitness
Expand All @@ -115,12 +126,14 @@ function configureMutateDict(options: IConfigureMutateDictOpt): any {
const extraBound = getBoundStateInfo(options.extraTarget);
Object.keys(dict).forEach((key) => (dict[key].extraBound = extraBound));
}

let watchFnCtxMap: Dict = {};
if (internal.enableMutate) {
watchAndCallMutateDict({ target, dict });
watchFnCtxMap = watchAndCallMutateDict({ target, dict });
}
const witnessDict: Dict<IMutateWitness> = {}; // 具体类型定义见 types-api multiDict
Object.keys(dict).forEach((desc) => {
witnessDict[desc] = makeWitness(target, desc, desc, internal);
witnessDict[desc] = makeWitness(target, { desc, oriDesc: desc, internal, watchFnCtx: watchFnCtxMap[desc] });
});
return witnessDict;
}
Expand Down
8 changes: 6 additions & 2 deletions packages/helux-core/src/factory/creator/mutateFn.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Dict } from '@helux/types';
import { enureReturnArr, isPromise, noop } from '@helux/utils';
import { FROM, SCOPE_TYPE } from '../../consts';
import { getRunningFn, getSafeFnCtx } from '../../factory/common/fnScope';
Expand Down Expand Up @@ -252,15 +253,16 @@ function initFnItem(internal: TInternal, fnItem: IMutateFnStdItem) {
export function watchAndCallMutateDict(options: IWatchAndCallMutateDictOptions) {
const { target, dict } = options;
const keys = Object.keys(dict);
if (!keys.length) return;
const watchFnCtxMap: Dict = {};
if (!keys.length) return watchFnCtxMap;
const internal = getInternal(target);
const { mutateFnDict, usefulName, forAtom, sharedRoot } = internal;
const emitErrToPlugin = (err: Error) => emitErr(internal, err);

keys.forEach((descKey) => {
const item = mutateFnDict[descKey];
// 开始映射 mutate 函数相关数据依赖关系
createWatchLogic(
watchFnCtxMap[descKey] = createWatchLogic(
({ sn, isFirstCall }) => {
if (isFirstCall) {
initFnItem(internal, item);
Expand Down Expand Up @@ -315,4 +317,6 @@ export function watchAndCallMutateDict(options: IWatchAndCallMutateDictOptions)
},
);
});

return watchFnCtxMap;
}
2 changes: 1 addition & 1 deletion packages/helux-core/src/helpers/fnRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function runWatch(fnCtx: IFnCtx, options: IRunFnOpt) {
return;
}

// simpleWatch 的依赖时转移进去的,不需要判死循环,否则会照成误判
// simpleWatch 的依赖是转移进去的,不需要判死循环,否则会照成误判
// 设定了 checkDeadCycle 为 false,不检查死循环
if (fnCtx.isSimpleWatch || !fnCtx.checkDeadCycle) {
return fnCtx.fn({ isFirstCall, triggerReasons, sn });
Expand Down
4 changes: 4 additions & 0 deletions packages/helux-core/src/types/base.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@ export interface IMutateWitness<T = any> {
run: MutateCall<T>;
/** 人工调用 mutate 配置里的异步函数 */
runTask: MutateTaskCall<T>;
/**
* 撤销 mutate 自动运行机制,这是一个不可逆的操作,执行后 mutate 将不再执行
*/
cancel: () => void;
/** 用户透传的原始描述值 */
oriDesc: string;
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/helux-demo-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"dependencies": {
"@types/react": ">=16.0.0",
"@types/react-dom": ">=16.0.0",
"helux": "^4.2.7",
"helux": "^4.3.2",
"react": ">=16.10.2",
"react-dom": ">=16.10.2"
},
Expand Down
28 changes: 28 additions & 0 deletions packages/helux-hooks-impl/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
# @helux/hooks-impl

## 4.3.2

### Patch Changes

- @helux/types@4.3.2
- @helux/utils@4.3.2

## 4.3.1

### Patch Changes

- @helux/types@4.3.1
- @helux/utils@4.3.1

## 4.3.0

### Minor Changes

- ac52a46: build(4.2.8): fix unwatch
- 5520458: build(4.2.7): fix unwatch

### Patch Changes

- Updated dependencies [ac52a46]
- Updated dependencies [5520458]
- @helux/types@4.3.0
- @helux/utils@4.3.0

## 4.2.7

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/helux-hooks-impl/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@helux/hooks-impl",
"version": "4.2.7",
"version": "4.3.2",
"description": "helux hooks implement lib",
"bugs": {
"url": "https://github.com/heluxjs/helux/issues"
Expand Down
31 changes: 31 additions & 0 deletions packages/helux-hooks/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# @helux/hooks

## 4.3.2

### Patch Changes

- @helux/hooks-impl@4.3.2
- @helux/types@4.3.2
- @helux/utils@4.3.2

## 4.3.1

### Patch Changes

- @helux/hooks-impl@4.3.1
- @helux/types@4.3.1
- @helux/utils@4.3.1

## 4.3.0

### Minor Changes

- ac52a46: build(4.2.8): fix unwatch
- 5520458: build(4.2.7): fix unwatch

### Patch Changes

- Updated dependencies [ac52a46]
- Updated dependencies [5520458]
- @helux/hooks-impl@4.3.0
- @helux/types@4.3.0
- @helux/utils@4.3.0

## 4.2.7

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/helux-hooks/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@helux/hooks",
"version": "4.2.7",
"version": "4.3.2",
"description": "helux hooks lib for react",
"keywords": [
"helux",
Expand Down
Loading

0 comments on commit 81740d9

Please sign in to comment.