Skip to content

Commit

Permalink
fix: refactor useMutation api (#1783)
Browse files Browse the repository at this point in the history
* fix: refactor useMutation api

* fix: refactor useMutation api
  • Loading branch information
brickspert authored Jul 27, 2022
1 parent 90c73ba commit 8244516
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ describe('useMutationObserver', () => {

it('should callback work when target style be changed', async () => {
const callback = jest.fn();
const { rerender } = renderHook(() => useMutationObserver(() => container, callback, options));
const { rerender } = renderHook(() => useMutationObserver(callback, () => container, options));
container.style.backgroundColor = '#000';
await rerender();
expect(callback).toBeCalled();
});

it('should callback work when target node tree be changed', async () => {
const callback = jest.fn();
const { rerender } = renderHook(() => useMutationObserver(() => container, callback, options));
const { rerender } = renderHook(() => useMutationObserver(callback, () => container, options));
const paraEl = document.createElement('p');
container.appendChild(paraEl);
await rerender();
Expand All @@ -34,7 +34,7 @@ describe('useMutationObserver', () => {

it('should not work when target is null', async () => {
const callback = jest.fn();
const { rerender } = renderHook(() => useMutationObserver(null, callback, options));
const { rerender } = renderHook(() => useMutationObserver(callback, null, options));
container.style.backgroundColor = '#000';
await rerender();
expect(callback).not.toBeCalled();
Expand Down
16 changes: 9 additions & 7 deletions packages/hooks/src/useMutationObserver/demo/demo1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,20 @@ const App: React.FC = () => {

const ref = useRef<HTMLDivElement>(null);

const callback: MutationCallback = (mutationsList) => {
mutationsList.forEach(() => setCount(count + 1));
};

useMutationObserver(ref, callback, { attributes: true });
useMutationObserver(
(mutationsList) => {
mutationsList.forEach(() => setCount(count + 1));
},
ref,
{ attributes: true },
);

return (
<div>
<div ref={ref} style={{ width, height: 30, border: '1px solid #000', marginBottom: 8 }}>
<div ref={ref} style={{ width, padding: 12, border: '1px solid #000', marginBottom: 8 }}>
current width:{width}
</div>
<button onClick={() => setWidth(width + 10)}>widening</button>
<button onClick={() => setWidth((w) => w + 10)}>widening</button>
<p>Mutation count {count}</p>
</div>
);
Expand Down
34 changes: 7 additions & 27 deletions packages/hooks/src/useMutationObserver/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ nav:

# useMutationObserver

A hook that provides the ability to watch for changes being made to the DOM tree
A hook that provides the ability to watch for changes being made to the DOM tree, refer to [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)

## Examples

Expand All @@ -17,40 +17,20 @@ A hook that provides the ability to watch for changes being made to the DOM tree

```typescript
useMutationObserver(
target: Target,
callback: MutationCallback,
target: Target,
options?: MutationObserverInit,
);
```

### Params
## Params

| Property | Description | Type | Default |
| -------- | --------------------- | ------------------------------------------------------------------- | ------- |
| target | DOM element or ref | `() => Element` \| `Element` \| `MutableRefObject<Element>` | |
| callback | The callback function | `(mutations: MutationRecord[], observer: MutationObserver) => void` | |
| options | Setting | `MutationObserverInit` | |
| target | DOM element or ref | `() => Element` \| `Element` \| `MutableRefObject<Element>` | - |
| callback | The callback function | `(mutations: MutationRecord[], observer: MutationObserver) => void` | - |
| options | Setting | `MutationObserverInit` | - |

### Options

| Property | Description | Type | Default |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------- |
| attributeFilter | An array of attribute names to be monitored. If this property isn't included, changes to all attributes cause mutation notifications | `string[]` | |
| attributeOldValue | Set to `true` to record the previous value of any attribute that changes when monitoring the node or nodes for attribute changes | `boolean` | |
| attributes | Set to `true` to watch for changes to the value of attributes on the node or nodes being monitored | `boolean` | `false` |
| characterData | Set to `true` to monitor the specified target node for changes to the character data contained within the node or nodes | `boolean` | |
| characterDataOldValue | Set to `true` to record the previous value of a node's text whenever the text changes on nodes being monitored | `boolean` | |
| childList | Set to `true` to monitor the target node for the addition nodes or removal nodes (if subtree is true, its descendants) | `boolean` | `false` |
| subtree | Set to `true` to extend monitoring to the entire subtree of nodes rooted at target | `boolean` | `false` |

### notice

Warning, Thrown in any of the following circumstances:

<!-- https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe#exceptions -->

- The options are configured such that nothing will actually be monitored. (For example, if childList, attributes, and characterData are all false.)

- The value of attributes is false (indicating that attribute changes are not to be monitored), but attributeOldValue is true and/or attributeFilter is present.

- The characterDataOldValue option is true but characterData is false (indicating that character changes are not to be monitored).
For options, please refer to [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe#parameters)
9 changes: 6 additions & 3 deletions packages/hooks/src/useMutationObserver/index.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
import { getTargetElement } from '../utils/domTarget';
import type { BasicTarget } from '../utils/domTarget';
import useDeepCompareEffectWithTarget from '../utils/useDeepCompareWithTarget';
import useLatest from '../useLatest';

const useMutationObserver = (
target: BasicTarget,
callback: MutationCallback,
target: BasicTarget,
options: MutationObserverInit = {},
): void => {
const callbackRef = useLatest(callback);

useDeepCompareEffectWithTarget(
() => {
const element = getTargetElement(target);
if (!element) {
return;
}
const observer = new MutationObserver(callback);
const observer = new MutationObserver(callbackRef.current);
observer.observe(element, options);
return () => {
if (observer) {
observer.disconnect();
}
};
},
[options, callback],
[options],
target,
);
};
Expand Down
32 changes: 6 additions & 26 deletions packages/hooks/src/useMutationObserver/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ nav:

# useMutationObserver

一个监听指定的 DOM 发生变化的 hook
一个监听指定的 DOM 树发生变化的 Hook,参考 [MutationObserver](https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver)

## 代码演示

Expand All @@ -17,8 +17,8 @@ nav:

```typescript
useMutationObserver(
target: Target,
callback: MutationCallback,
target: Target,
options?: MutationObserverInit,
);
```
Expand All @@ -27,30 +27,10 @@ useMutationObserver(

| 参数 | 说明 | 类型 | 默认值 |
| -------- | ---------------- | ------------------------------------------------------------------- | ------ |
| target | DOM 节点或者 Ref | `Element` \| `() => Element` \| `MutableRefObject<Element>` | |
| callback | 触发的回调函数 | `(mutations: MutationRecord[], observer: MutationObserver) => void` | |
| options | 设置项 | `MutationObserverInit` | |
| callback | 触发的回调函数 | `(mutations: MutationRecord[], observer: MutationObserver) => void` | - |
| target | DOM 节点或者 Ref | `Element` \| `() => Element` \| `MutableRefObject<Element>` | - |
| options | 设置项 | `MutationObserverInit` | `{}` |

### Options

| 参数 | 说明 | 类型 | 默认值 |
| --------------------- | ---------------------------------------------------------------------------------------- | ---------- | ------- |
| attributeFilter | 要监视的特定属性名称的数组。如果未包含此属性,则对所有属性的更改都会触发变动通知 | `string[]` | |
| attributeOldValue | 当监视节点的属性改动时,将此属性设为 `true` 将记录任何有改动的属性的上一个值 | `boolean` | |
| attributes | 设为 `true` 以观察受监视元素的属性值变更 | `boolean` | `false` |
| characterData | 设为 `true` 以监视指定目标节点或子节点树中节点所包含的字符数据的变化 | `boolean` | |
| characterDataOldValue | 设为 `true` 以在文本在受监视节点上发生更改时记录节点文本的先前值 | `boolean` | |
| childList | 设为 `true` 以监视目标节点添加或删除新的子节点(如果 subtree 为 true,则也包含子孙节点) | `boolean` | `false` |
| subtree | 设为 `true` 以将监视范围扩展至目标节点整个节点树中的所有节点 | `boolean` | `false` |

### notice

注意,以下任一情况都会抛出异常:

<!-- https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver/observe#%E5%BC%82%E5%B8%B8 -->

-`options` 配置项对象中,必须至少将 `attributes``characterData``childList` 中的一个属性设置为 `true`,否则会报错

- `attributes` 选项为 `false`(表示不监视属性更改),但是 `attributeOldValue` 选项为 `true` 并且/或者 `attributeFilter` 配置存在

- `characterDataOldValue` 选项为 `true`,但是 `characterData` 选项为 `false`(表示不跟踪字符更改)
配置项请参考 [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe#parameters)

0 comments on commit 8244516

Please sign in to comment.