Skip to content

Commit 6190f18

Browse files
authored
feat(state-wire): add useSubscribe hook (#19)
1 parent 562ad25 commit 6190f18

File tree

5 files changed

+101
-1
lines changed

5 files changed

+101
-1
lines changed

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ connect react components with wire
2020
- [Global wire](#global-wire)
2121
- [`useSelector` hook](#useselector-hook)
2222
- [`createSelector` function](#createselector-function)
23+
- [`useSubscribe` hook](#usesubscribe-hook)
2324
- [Subscribe to the wire](#subscribe-to-the-wire)
2425
- [`useInterceptor` hook](#useinterceptor-hook)
2526
- [Notes](#notes)
@@ -277,9 +278,22 @@ function SomeComponent() {
277278
}
278279
```
279280

281+
### `useSubscribe` hook
282+
283+
Every time the wire value changes, the callback function would be called
284+
285+
```tsx
286+
// subscribe
287+
useSubscribe(
288+
useCallback(value => {
289+
/* ... */
290+
}, []),
291+
);
292+
```
293+
280294
### Subscribe to the wire
281295

282-
Every time wire value changed the callback function will be called
296+
Every time the wire value changes, the callback function would be called
283297

284298
<details>
285299
<summary>more detail</summary>

index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,11 @@ export declare function useSelector<V, Fns = {}>(
184184
options: ReadOnlySelectorOptions<V>,
185185
): ReadonlyWire<V, Fns>;
186186

187+
export declare function useSubscribe<V>(
188+
wire: ReadonlyStateWire<V>,
189+
callback: (value: Defined<V>) => void,
190+
): void;
191+
187192
export declare function useWire<V, Fns = {}>(
188193
upLink: Wire<V, Fns>,
189194
): Wire<V, Fns>;

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ export { useFn } from './fn-wire/use-fn';
1414
export { createWire } from './wire/create-wire';
1515
export { createSelector } from './selector/create-selector';
1616
export { useSelector } from './selector/use-selector';
17+
export { useSubscribe } from './state-wire/use-subscribe';

src/state-wire/use-subscribe.test.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { renderHook } from '@testing-library/react-hooks';
2+
import { useCallback } from 'react';
3+
import { act } from 'react-dom/test-utils';
4+
import { useStateWire } from './use-state-wire';
5+
import { useSubscribe } from './use-subscribe';
6+
7+
describe('useSubscribe', () => {
8+
it('should not call the callback function on subscribing', () => {
9+
const fn = jest.fn();
10+
11+
renderHook(() => {
12+
const wire = useStateWire(null, 5);
13+
useSubscribe(
14+
wire,
15+
useCallback(value => {
16+
fn(value);
17+
}, []),
18+
);
19+
return { wire };
20+
});
21+
expect(fn).not.toBeCalled();
22+
});
23+
24+
it('should call the callback function when the wire value updates', () => {
25+
const fn = jest.fn();
26+
27+
const { result } = renderHook(() => {
28+
const wire = useStateWire(null, 5);
29+
useSubscribe(
30+
wire,
31+
useCallback(value => {
32+
fn(value);
33+
}, []),
34+
);
35+
return { wire };
36+
});
37+
act(() => {
38+
result.current.wire.setValue(3);
39+
});
40+
41+
expect(fn).toBeCalledWith(3);
42+
});
43+
44+
it('should not call the callback function after unmount', () => {
45+
const fn = jest.fn();
46+
47+
const { result, unmount } = renderHook(() => {
48+
const wire = useStateWire(null, 5);
49+
useSubscribe(
50+
wire,
51+
useCallback(value => {
52+
fn(value);
53+
}, []),
54+
);
55+
return { wire };
56+
});
57+
act(() => {
58+
unmount();
59+
});
60+
act(() => {
61+
result.current.wire.setValue(3);
62+
});
63+
64+
expect(fn).not.toBeCalled();
65+
});
66+
});

src/state-wire/use-subscribe.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { useEffect } from 'react';
2+
import { Defined } from '../utils/type-utils';
3+
import { useStabilityGuard } from '../utils/use-stability-guard';
4+
import { ReadonlyStateWire } from './readonly-state-wire';
5+
6+
export function useSubscribe<V>(
7+
wire: ReadonlyStateWire<V>,
8+
callback: (value: Defined<V>) => void,
9+
): void {
10+
useStabilityGuard(wire);
11+
useEffect(() => {
12+
return wire.subscribe(callback);
13+
}, [wire, callback]);
14+
}

0 commit comments

Comments
 (0)