Skip to content

Commit

Permalink
Merge pull request #114 from heluxjs/doc
Browse files Browse the repository at this point in the history
[released 4.0.3]
  • Loading branch information
fantasticsoul authored Jan 6, 2024
2 parents f296aa6 + 19b582b commit 5685406
Show file tree
Hide file tree
Showing 38 changed files with 397 additions and 63 deletions.
1 change: 1 addition & 0 deletions docs/docs/api/base/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ nav:
- [runMutateTask](/api/base/run-mutate-task) 人工触发可变派生函数异步任务
- [action](/api/base/action) 创建修改状态的 action 同步或异步函数
- [watch](/api/base/watch) 创建观察数据变化的监听函数
- [watchEffect](/api/base/watch-effect) 创建观察数据变化的监听函数,立即运行并在首次运行时收集到依赖
- [syncer](/api/base/syncer) 浅层次对象的同步函数生成器,辅助双向绑定
- [sync](/api/base/sync) 深层次对象的同步函数生成器,辅助双向绑定
- [emit](/api/base/emit) 发射事件
Expand Down
28 changes: 28 additions & 0 deletions docs/docs/api/base/watch-effect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
group:
title: 帮助
order: 4
order: 0
---

# watchEffect

`watchEffect`用于观察数据变化,并做对应的处理逻辑,观察的粒度可以任意定制。

区别于`watch``watchEffect`回调会立即执行,自动对首次运行时函数内读取到的值完成变化监听。

:::info
本章节展示基础用法,更多用法查阅[指南/观察](/guide/watch)[基础api/观察](/api/base/watch)
:::

## 基础用法

```ts
import { watchEffect, getSnap } from ' helux ';
const [priceState, setPrice] = share({ a: 1 });

// 观察 priceState.a 的变化
watchEffect(() => {
console.log(`found price.a changed from ${getSnap(priceState).a} to ${priceState.a}`);
});
```
8 changes: 6 additions & 2 deletions docs/docs/api/base/watch.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ watch 可观察共享状态跟对象的变化,第二位参数可写为`()=>[]`

## 死循环

设置`immediate`为 true 时,watch 回调首次执行会自动收集依赖,此时如果存在读取自己修改自己的新闻,则会造成死循环
设置`immediate`为 true 时,watch 回调首次执行会自动收集依赖,此时如果存在读取自己修改自己的行为,会造成死循环。

:::tip
死循环产生后,框架会定位到具体的函数位置并告知原因,用户可打开控制台查看
:::

```ts
import { watch, atom } from 'helux';
Expand All @@ -36,7 +40,7 @@ const [state, setAtom] = atom({ a: 1 });

watch(
() => {
//单独 a 修改 a,触发死循环
//读取 a 修改 a,触发死循环
setAtom((draft) => {
draft.a += 1;
});
Expand Down
1 change: 1 addition & 0 deletions docs/docs/api/hooks/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ order: 0
- [useDerived](/api/hooks/use-derived) 使用全量派生结果
- [useOnEvent](/api/hooks/use-on-event) 使用事件监听
- [useWatch](/api/hooks/use-watch) 使用观察
- [useWatchEffect](/api/hooks/use-watch-effect) 使用观察,立即运行并在首次运行时收集到依赖
- [useGlobalId](/api/hooks/use-global-id) 使用`globalId`
- [useMutate](/api/hooks/use-mutate) 使用可变本地状态
- [useService](/api/hooks/use-service) 使用服务
Expand Down
49 changes: 49 additions & 0 deletions docs/docs/api/hooks/use-watch-effect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
order: 4
---

# useWatchEffect

`useWatchEffect` 功能同 `watchEffect``一样,区别在于 `useWatchEffect` 会立即执行回调,自动对首次运行时函数内读取到的值完成变化监听。

:::info
其他使用方式可参考[watchEffect](/api/hooks/use-effect)
:::


## 基础用法

:::info
`useWatchEffect`回调的首次运行的执行时机是在组件挂载完毕后才执行
:::

```tsx
/**
* defaultShowCode: true
*/
import { share, useMutable, useWatchEffect, getSnap } from 'helux';

const [priceState, setState, ctx] = share({ a: 1, b: { b1: { b2: 200 } } });

function changeA() {
setState((draft) => {
draft.a += 1;
});
}

export default function Comp(props: any) {
const [ state, setState] = useMutable({tip:'1'})
useWatchEffect(() => {
setState(draft=>{
draft.tip = `priceState.a changed from ${getSnap(priceState).a} to ${priceState.a}`;
});
});

return (
<div>
<button onClick={changeA}>changeA</button>
<h1>tip: {state.tip}</h1>
</div>
);
}
```
4 changes: 4 additions & 0 deletions docs/docs/api/hooks/use-watch.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ interface IWatchOptions {
type WatchFnDeps = () => any[] | undefined;
```

:::info
`useWatch`回调的首次运行的执行时机是在组件挂载完毕后才执行
:::

## 基础用法

### 观察原始类型 atom
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ nav:
> - [runMutateTask](/api/base/run-mutate-task) 人工触发可变派生函数异步任务
> - [action](/api/base/action) 创建修改状态的 action 同步或异步函数
> - [watch](/api/base/watch) 创建观察数据变化的监听函数
> - [watchEffect](/api/base/watch-effect) 创建观察数据变化的监听函数,立即运行并在首次运行时收集到依赖
> - [syncer](/api/base/syncer) 浅层次对象的同步函数生成器,辅助双向绑定
> - [sync](/api/base/sync) 深层次对象的同步函数生成器,辅助双向绑定
> - [emit](/api/base/emit) 发射事件
Expand Down Expand Up @@ -56,6 +57,7 @@ ctx.aciton()(/** action 函数定义 */)
> - [useDerived](/api/hooks/use-derived) 使用全量派生结果
> - [useOnEvent](/api/hooks/use-on-event) 使用事件监听
> - [useWatch](/api/hooks/use-watch) 使用观察
> - [useWatchEffect](/api/hooks/use-watch-effect) 使用观察,立即运行并在首次运行时收集到依赖
> - [useGlobalId](/api/hooks/use-global-id) 使用`globalId`
> - [useMutate](/api/hooks/use-mutate) 使用可变本地状态
> - [useService](/api/hooks/use-service) 使用服务
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/guide/atom.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const { state: numAtom, setState: setAtom } = atomCtx;

钩子 `useAtom` 返回一个元组,使用方式大体对齐 `react.useState` 接口,唯一的区别是`setter`提供的回调参数是一个草稿对象,可基于草稿对象直接修改,这个差异点下面会再次提到。

:::info{title=推荐通过 actions 修改}
:::info{title='通过 actions 修改'}
推荐了解和使用[模块化/defineAtcions](/guide/modular#defineactions)定义修改方法,有利于维护或扩展
:::

Expand Down
31 changes: 30 additions & 1 deletion docs/docs/guide/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const [numAtom, setAtom] = atom(1);
setAtom(100);
```

字典对象修改,基于回调的草稿对象直接修改即可
字典对象修改,基于`setAtom`接口回调里的草稿对象直接修改即可

```ts
const [numAtom, setAtom] = atom({ a: 1, b: { b1: 1 } });
Expand All @@ -45,6 +45,35 @@ setAtom((draft) => {
});
```

或基于`reactive`响应式对象修改,数据变更在下一次事件循环微任务开始前被提交。

```ts
const [numAtom, setAtom, {reactive}] = atom({ a: 1, b: { b1: 1 } });
function change(){
reactive.b.b1 += 1;
}
```

或定义`action`修改

```ts
const [numAtom, setAtom, { action, defineActions }] = atom({ a: 1, b: { b1: 1 } });
// 方式1:裸写 action
const change = action()(({draft})=>{
draft.b.b1 += 1;
}, 'change');
change(); // 触发变更

// 方式2:调用可读性更友好的 defineActions
const { actions } = defineActions()({
change({draft}){
draft.b.b1 += 1;
},
// 可以继续定义其他 action
});
actions.change(); // 触发变更
```

## 观察 atom

可观察整个根对象变化,也可以观察部分节点变化
Expand Down
29 changes: 29 additions & 0 deletions docs/docs/guide/reactive.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,32 @@ export default () => (
</Entry>
);
```

## 修改 input 组件

`input`组件实时输入过程中,需主动调用`flush`接口刷新状态,避免中文输入法出现中文无法提示的问题。

```tsx
/**
* defaultShowCode: true
*/
import { sharex } from 'helux';
const { reactive, useState, flush } = sharex({ str: '' });
function change(e) {
reactive.str = e.target.value;
// 去掉 flush 调用,中文输入法无法录入汉字
flush();
}

function Demo(){
const [ state ] = useState();
return <input value={state.str} onChange={change} />;
}

export default () => (
<>
<Demo />
<Demo />
</>
);
```
55 changes: 55 additions & 0 deletions docs/docs/guide/watch.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ order: 8

## 组件外观察变化

### watch

使用`watch`可观察 atom 对象自身变化或任意多个子节点的变化。

观察函数立即执行,首次执行时收集到相关依赖
Expand Down Expand Up @@ -86,8 +88,24 @@ watch(
);
```

### watchEffect

`watchEffect`回调会立即执行,自动对首次运行时函数内读取到的值完成变化监听

```ts
import { watchEffect, getSnap } from ' helux ';
const [priceState, setPrice] = share({ a: 1 });

// 观察 priceState.a 的变化
watchEffect(() => {
console.log(`found price.a changed from ${getSnap(priceState).a} to ${priceState.a}`);
});
```

## 组件内观察变化

### useWatch

提供`useWatch`让客户在组件内部观察变化

:::success{title=自动销毁观察监听}
Expand Down Expand Up @@ -176,3 +194,40 @@ export default () => (
</div>
);
```

### useWatchEffect

在组件中使用 `useWatchEffect` 来完成状态变化监听,会在组件销毁时自动取消监听。

`useWatchEffect` 功能同 `watchEffect``一样,区别在于 `useWatchEffect` 会立即执行回调,自动对首次运行时函数内读取到的值完成变化监听。

```tsx
/**
* defaultShowCode: true
*/
import { share, useMutable, useWatchEffect, getSnap } from 'helux';

const [priceState, setState, ctx] = share({ a: 1, b: { b1: { b2: 200 } } });

function changeA() {
setState((draft) => {
draft.a += 1;
});
}

export default function Comp(props: any) {
const [ state, setState] = useMutable({tip:'1'})
useWatchEffect(() => {
setState(draft=>{
draft.tip = `priceState.a changed from ${getSnap(priceState).a} to ${priceState.a}`;
});
});

return (
<div>
<button onClick={changeA}>changeA</button>
<h1>tip: {state.tip}</h1>
</div>
);
}
```
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"@makotot/ghostui": "^2.0.0",
"animated-scroll-to": "^2.3.0",
"classnames": "^2.5.0",
"helux": "4.0.2",
"helux": "4.0.3",
"lodash": "^4.17.21",
"lodash.throttle": "^4.1.1",
"prism-react-renderer": "^2.3.1",
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.0.2",
"version": "4.0.3",
"description": "A state engine integrates atom, signal, derive, watch and dep tracking, supports fine-grained responsive updates, it is compatible with all react like libs (including React 18).",
"keywords": [],
"author": {
Expand Down
2 changes: 2 additions & 0 deletions packages-legacy/helux-preact/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ export const {
runDeriveTask,
// watch api
watch,
watchEffect,
// hooks api
useAtom,
useAtomX,
useReactive,
useReactiveX,
useDerived,
useWatch,
useWatchEffect,
useGlobalId,
useService,
useOnEvent,
Expand Down
9 changes: 9 additions & 0 deletions packages/helux-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# @helux/core

## 4.0.3

### Patch Changes

- 6be67ec: feat: add watchEffect, useWatchEffect
- @helux/hooks-impl@4.0.3
- @helux/types@4.0.3
- @helux/utils@4.0.3

## 4.0.2

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/helux-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@helux/core",
"version": "4.0.2",
"version": "4.0.3",
"description": "A state library core integrates atom, signal, collection dep, derive and watch, it supports all react like frameworks.",
"bugs": {
"url": "https://github.com/heluxjs/helux/issues"
Expand Down Expand Up @@ -35,7 +35,7 @@
"@helux/hooks-impl": "workspace:^",
"@helux/types": "workspace:^",
"@helux/utils": "workspace:^",
"limu": "^3.12.0"
"limu": "^3.12.1"
},
"devDependencies": {
"esbuild-copy-static-files": "^0.1.0"
Expand Down
Loading

0 comments on commit 5685406

Please sign in to comment.