Skip to content

Commit

Permalink
feat: add doc
Browse files Browse the repository at this point in the history
  • Loading branch information
fantasticsoul committed Dec 27, 2023
1 parent f2a675c commit dd31fea
Show file tree
Hide file tree
Showing 135 changed files with 2,771 additions and 2,024 deletions.
42 changes: 42 additions & 0 deletions doc/docs/tutorial/compare-state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
sidebar_position: 3
---

# 比较状态

对象值修改,回调提供的一个可直接修改的草稿代理对象,可基于该对象修改任意节点数据,生成的新状态和旧状态是结构共享的数据,

## isDiff

对象型节点可借助`isDiff`函数比较是否相等

```ts
import { isDiff } from 'helux';

const { b, c } = state1.val;
setAtom((draft) => (draft.b.b1 = 100));
const { b: newB, c: newC } = state1.val;

// 👉 此时 b,c 节点是代理对象,直接比较的话,它们始终是不相等的,
// 而 isDiff 函数内部会比较数据版本号并给出正确的结果
isDiff(b, newB); // true
isDiff(c, newC); // false,c 节点未发生过变化
```

## getSnap

也可以借助`getSnap`函数获取快照对象来直接比较

```ts
import { getSnap } from 'helux';

const snap1 = getSnap(state1); // 修改前的快照
setAtom((draft) => (draft.b.b1 = 100));
const snap2 = getSnap(state1); // 修改后的快照
const { b: newB, c: newC } = state1.val;

console.log(snap1.val.b !== snap2.val.b); // true
console.log(snap1.val.c !== snap2.val.c); // false,c 节点未发生过变化
```

其余文档正在拼命建设中,有疑问可联系 [fantasticsoul](https://github.com/fantasticsoul) 或提 [issue](https://github.com/heluxjs/helux/issues) ....
39 changes: 0 additions & 39 deletions doc/docs/tutorial/intro.mdx

This file was deleted.

194 changes: 194 additions & 0 deletions doc/docs/tutorial/modify-state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
---
sidebar_position: 2
---

# 修改状态

`helux`严格遵循读写分离原则,`atom``share` 创建的共享状态是只读状态

```ts
const [state] = atom({ a: 1, b: { b1: 1, b2: 2 } });
state.b.b1 = 100; // ❌ 修改失败,控制会给出警告
console.log(state.b.b1); // 1
```

可通过以下方式修改共享状态

- 使用`atom``share`接口返回的修改句柄修改
- 使用 `reactive` 响应式对象修改
- 使用 `action` 定义方法后触发对应方法去修改

## setState

`atom``share`接口返回的元组第二位是修改状态的句柄

```ts
// 👇 修改状态句柄
const [state1, setAtom] = atom({ a: 1, b: { b1: 1, b2: 2 } });
// 👇 修改状态句柄
const [state1, setState] = share({ a: 1, b: { b1: 1, b2: 2 } });
```

也可以通过 ctx 对象获得`setState`句柄

```ts
const [, , ctx] = atom({ a: 1, b: { b1: 1, b2: 2 } });
const [, , ctx] = share({ a: 1, b: { b1: 1, b2: 2 } });
ctx.setState; // 👈 修改状态句柄

// 或者
const ctx = atomx({ a: 1, b: { b1: 1, b2: 2 } });
const ctx = sharex({ a: 1, b: { b1: 1, b2: 2 } });
ctx.setState; // 👈 修改状态句柄
```

### 直接传递新状态

原始值修改

```ts
const [state1, setAtom] = atom(1);

console.log(state1.val); // 1
setAtom(100);
console.log(state1.val); // 100
```

对象修改

```ts
const [state1, setAtom] = atom({ a: 1, b: { b1: 1, b2: 2 } });
const [state2, setShared] = share({ a: 1, b: { b1: 1, b2: 2 } });

// 注:此处 state1 需来自 atom 创建,需 .val 取值
console.log(state1.val.a); // 1
console.log(state2.a); // 1

// set 句柄内部会自动装箱,故 setAtom、setShared 调用方式一样
setAtom({ a: 100, b: { b1: 1, b2: 2 } });
setShared({ a: 100, b: { b1: 1, b2: 2 } });

console.log(state1.val.a); // 100
console.log(state2.a); // 100
```

### 回调里返回新状态

原始值修改,返回新值

```ts
const [state1, setAtom] = atom(1);

// 返回新值
setAtom(() => 100);
// 返回新值(基于上一刻的值)
setAtom((prev) => prev + 100);
```

对象值修改,返回部分值,内部会做浅合并操作

```ts
const [state1, setAtom] = atom({ a: 100, b: { b1: 1, b2: 2 }, c: { c1: 1, c2: 2 } });

// 内部会完成 newState = { ...prevState, b: { b1: 100, b2: 200 } } 操作
setAtom(() => ({ b: { b1: 100, b2: 200 } }));
```

对象值修改,返回新值,替换整个状态(相当于内部的浅合并把整个状态之前的值都覆盖了)

```ts
const [state1, setAtom] = atom({ a: 100, b: { b1: 1, b2: 2 }, c: { c1: 1, c2: 2 } });

// 内部会完成 newState = { ...prevState, ...newPartial } 操作
setAtom(() => ({ a: 1, b: { b1: 100, b2: 200 }, c: { c1: 100, c2: 200 } }));
```

### 回调里修改部分状态

针对对象值修改部分数据的场景,回调参数列表同事提供了一个可直接修改的草稿代理对象,可基于该草稿对象修改任意节点数据,生成的新状态和旧状态是结构共享的数据,可阅读[比较对象](/docs/tutorial/compare-state)了解更多。

```ts
const [state1, setAtom] = atom({ a: 100, b: { b1: 1, b2: 2 }, c: { c1: 1, c2: 2 } });

// 仅修改 b.b1 的值,(注此处的 draft 已自动拆箱)
setAtom((draft) => {
draft.b.b1 = 100;
});
```

:::caution 箭头函数隐式返回值

这样的写法`setAtom((draft)=>draft.b.b1 = 100)` ts 是编译不通过的,因为箭头函数隐含返回了`100`,这个值时不能不作为部分状态合并到字典里的,故此处使用了``setAtom((draft)=>{draft.b.b1 = 100})` 带花括号的箭头函数写法来消除这个隐式返回值

:::

除了带花括号的箭头函数写法,还可以使用`setDraft`接口来消除这个编译错误,`setDraft`内部忽略函数任意返回值

```ts
const [state1, setAtom, ctx] = atom({ a: 100, b: { b1: 1, b2: 2 }, c: { c1: 1, c2: 2 } });
// ctx.setDraft((draft) => draft.b.b1 = 100); // 👈 此处箭头函数体无花括号包裹也能正常编译通过

// 也可使用 atomx 获得 ctx,此时可写为 const ctx = atomx(...); ctx.setDraft(...)
```

Map 对象值修改

```ts
const [state1, setAtom] = atom(
new Map([
[1, { id: 1, name: '1' }],
[2, { id: 2, name: '2' }],
]),
);

// 仅修改 key 为 1 对应的值,(注此处的 draft 已自动拆箱)
setAtom((draft) => (draft.get(1).name = 'new'));
```

List 对象值修改

```ts
const [state1, setAtom] = atom([
{ id: 1, name: '2' },
{ id: 1, name: '2' },
]);
setAtom((draft) => (draft[0].name = 'new'));
```

### 回调里修改、返回部分状态
`setState`接口支持回调里修改既修改部分状态,同时也返回部分状态

```ts
const [state1, setAtom] = atom({ a: 100, b: { b1: 1, b2: 2 }, c: { c1: 1, c2: 2 } });

setAtom(draft=>{
draft.b.b1 = 100;
return { a: 1 }; // 👈 等效于写为:draft.a = 1
});

```

## reactive

helux 提供全局响应式对象做修改,修改值会在下一次微任务循环开始时提交并同步到只读代理上

```ts
// 此处使用 atomx 替代 atom,方便一次解构即可获取 reactive 对象
const { state, reactive } = atomx({ a: 100, b: { b1: 1, b2: 2 }, c: { c1: 1, c2: 2 } });

async function modStateByReactive(){
reactive.b.b1 = 100;
reactive.c.c1 = 100;
console.log(reactive.b.b1); // 100
console.log(reactive.c.c1); // 100
console.log(state.b.b1); // 1
console.log(state.c.c1); // 1
await Promise.resolve(1);
console.log(state.b.b1); // 100
console.log(state.c.c1); // 100
}

```


其余文档正在拼命建设中,有疑问可联系 [fantasticsoul](https://github.com/fantasticsoul) 或提 [issue](https://github.com/heluxjs/helux/issues) ....
Loading

0 comments on commit dd31fea

Please sign in to comment.