Skip to content

Commit b3e8a0a

Browse files
author
Brian Vaughn
committed
Tidied things up, added Flow types, etc
1 parent 8fa0898 commit b3e8a0a

File tree

2 files changed

+32
-24
lines changed

2 files changed

+32
-24
lines changed

packages/react-hooks/src/__tests__/useSubscription-test.internal.js

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,16 @@ describe('useSubscription', () => {
5151

5252
// Mimic createSubscription API to simplify testing
5353
function createSubscription({getCurrentValue, subscribe}) {
54+
function DefaultChild({value = 'default'}) {
55+
Scheduler.yieldValue(value);
56+
return null;
57+
}
58+
5459
return function Subscription({children, source}) {
5560
const value = useSubscription(
5661
React.useMemo(() => ({source, getCurrentValue, subscribe}), [source]),
5762
);
58-
59-
return React.createElement(children, {value});
63+
return React.createElement(children || DefaultChild, {value});
6064
};
6165
}
6266

@@ -71,12 +75,7 @@ describe('useSubscription', () => {
7175

7276
const observable = createBehaviorSubject();
7377
const renderer = ReactTestRenderer.create(
74-
<Subscription source={observable}>
75-
{({value = 'default'}) => {
76-
Scheduler.yieldValue(value);
77-
return null;
78-
}}
79-
</Subscription>,
78+
<Subscription source={observable} />,
8079
{unstable_isConcurrent: true},
8180
);
8281

@@ -110,14 +109,9 @@ describe('useSubscription', () => {
110109
},
111110
});
112111

113-
function render({value = 'default'}) {
114-
Scheduler.yieldValue(value);
115-
return null;
116-
}
117-
118112
let observable = createReplaySubject('initial');
119113
const renderer = ReactTestRenderer.create(
120-
<Subscription source={observable}>{render}</Subscription>,
114+
<Subscription source={observable} />,
121115
{unstable_isConcurrent: true},
122116
);
123117
expect(Scheduler).toFlushAndYield(['initial']);
@@ -128,7 +122,7 @@ describe('useSubscription', () => {
128122

129123
// Unsetting the subscriber prop should reset subscribed values
130124
observable = createReplaySubject(undefined);
131-
renderer.update(<Subscription source={observable}>{render}</Subscription>);
125+
renderer.update(<Subscription source={observable} />);
132126
expect(Scheduler).toFlushAndYield(['default']);
133127
});
134128

@@ -141,24 +135,19 @@ describe('useSubscription', () => {
141135
},
142136
});
143137

144-
function render({value = 'default'}) {
145-
Scheduler.yieldValue(value);
146-
return null;
147-
}
148-
149138
const observableA = createBehaviorSubject('a-0');
150139
const observableB = createBehaviorSubject('b-0');
151140

152141
const renderer = ReactTestRenderer.create(
153-
<Subscription source={observableA}>{render}</Subscription>,
142+
<Subscription source={observableA} />,
154143
{unstable_isConcurrent: true},
155144
);
156145

157146
// Updates while subscribed should re-render the child component
158147
expect(Scheduler).toFlushAndYield(['a-0']);
159148

160149
// Unsetting the subscriber prop should reset subscribed values
161-
renderer.update(<Subscription source={observableB}>{render}</Subscription>);
150+
renderer.update(<Subscription source={observableB} />);
162151
expect(Scheduler).toFlushAndYield(['b-0']);
163152

164153
// Updates to the old subscribable should not re-render the child component

packages/react-hooks/src/useSubscription.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
110
import {useEffect, useState} from 'react';
211

3-
export function useSubscription({
12+
// Hook used for safely managing subscriptions in concurrent mode.
13+
//
14+
// In order to avoid removing and re-adding subscriptions each time this hook is called,
15+
// the parameters passed to this hook should be memoized in some way–
16+
// either by wrapping the entire params object with useMemo()
17+
// or by wrapping the individual callbacks with useCallback().
18+
export function useSubscription<Value, Source>({
419
// This is the thing being subscribed to (e.g. an observable, event dispatcher, etc).
520
source,
621

@@ -10,7 +25,11 @@ export function useSubscription({
1025
// This function is passed an event handler to attach to the subscription source.
1126
// It should return an unsubscribe function that removes the handler.
1227
subscribe,
13-
}) {
28+
}: {|
29+
source: Source,
30+
getCurrentValue: (source: Source) => Value,
31+
subscribe: (source: Source, callback: Function) => () => void,
32+
|}) {
1433
// Read the current value from our subscription source.
1534
// When this value changes, we'll schedule an update with React.
1635
// It's important to also store the source itself so that we can check for staleness.

0 commit comments

Comments
 (0)