1
- import { useEffect , useReducer , useState } from 'react' ;
1
+ import { useEffect , useState } from 'react' ;
2
2
3
3
export function useSubscription ( {
4
4
// This is the thing being subscribed to (e.g. an observable, event dispatcher, etc).
@@ -39,25 +39,35 @@ export function useSubscription({
39
39
// (Learn more at https://codesandbox.io/s/k0yvr5970o)
40
40
useEffect (
41
41
( ) => {
42
+ let didUnsubscribe = false ;
43
+
42
44
const checkForUpdates = ( ) => {
43
- setState ( state => {
45
+ // It's possible that this callback will be invoked even after being unsubscribed,
46
+ // if it's removed as a result of an event/update from the source.
47
+ // In this case, React will log a DEV warning about an update from an unmounted component.
48
+ // We can avoid triggering that warning with this check.
49
+ if ( didUnsubscribe ) {
50
+ return ;
51
+ }
52
+
53
+ setState ( prevState => {
44
54
// Ignore values from stale sources!
45
55
// Since we subscribe an unsubscribe in a passive effect,
46
56
// it's possible that this callback will be invoked for a stale (previous) source.
47
57
// This check avoids scheduling an update for htat stale source.
48
- if ( state . source !== source ) {
49
- return state ;
58
+ if ( prevState . source !== source ) {
59
+ return prevState ;
50
60
}
51
61
52
62
// Some subscription sources will auto-invoke the handler, even if the value hasn't changed.
53
63
// If the value hasn't changed, no update is needed.
54
64
// Return state as-is so React can bail out and avoid an unnecessary render.
55
65
const value = getCurrentValue ( source ) ;
56
- if ( state . value === value ) {
57
- return state ;
66
+ if ( prevState . value === value ) {
67
+ return prevState ;
58
68
}
59
69
60
- return { ...state , value } ;
70
+ return { ...prevState , value} ;
61
71
} ) ;
62
72
} ;
63
73
const unsubscribe = subscribe ( source , checkForUpdates ) ;
@@ -67,7 +77,10 @@ export function useSubscription({
67
77
// Check for this and schedule an update if work has occurred.
68
78
checkForUpdates ( ) ;
69
79
70
- return ( ) => unsubscribe ( ) ;
80
+ return ( ) => {
81
+ didUnsubscribe = true ;
82
+ unsubscribe ( ) ;
83
+ } ;
71
84
} ,
72
85
[ getCurrentValue , source , subscribe ] ,
73
86
) ;
0 commit comments