-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The BehaviorSubject
of useObservable
could cause resource leaks
#123
Comments
Any comments? Would love to open a PR for this. |
Hi thanks for the info and sorry for the late reply. I have not come up with a clean and safe solution for calling |
Two approaches I could think of:
|
Thank you for the replies. As for the first approach, I think it introduces too many breaking changes and breaks the simplicity of the library. As for the second one, I don't get what you mean. By "extra effects", do you mean the fact that in StrctMode the cleanup function of |
Not just the cleanup but the |
Sorry for the late reply. I get what you are referring to and notice the difficulties of leveraging the An alternative could be to require users to disable With the release of React 18, it seems that The changes to |
The reason that React calls I too think this is an unrealistic design and go against ergonomics. They tried to push it for over two years and responses from the community does not seem well (too hard or even impossible for library authors to implement). Nevertheless, I still want to keep it from breaking in StrictMode. The LeetCode team has moved away from I also lean toward the second approach. To avoid delaying |
I'm of the opinion that this doesn't relate to the concurrent mode features. Everything that takes place within Detecting |
Just stumbling across this issue. It's not clear to me that there is an actual problem here @darkyzhou, but maybe I'm not fully understanding it. The issue at hand is that the internal If this is accurate, I don't think this actually matters as, in this scenario, the Am I misunderstanding something @darkyzhou ? Is it possible for the observable created by |
You are right. As for garbage collection there seems to be no problems. Sorry for not being clear about what I am actually referring to for "resource leaks". When I mention "resources", I'm referring to ongoing side effects that need to be cancelled or explicitly signaled to stop when the |
Is this possible though? The only failure scenario that I can see occurs when If you try a hybrid approach, e.g. using a factory function that, internally, makes use of an observable created in outside context, then presumably that outside observable would be used inside a For example: declare const otherObservable: Observable<boolean>;
useObservable(
(inputs$) =>
inputs$.pipe(
switchMap(([inputValue]) =>
return inputValue ? otherObservable : NEVER
)
)
) I guess I don't know about |
Would something like this work: const useReactLifecycleObservable = (): Observable<unknown> => {
const reactLifecycleEndSubject = useMemo(() => new Subject<unknown>(), []);
useEffect(() => () => {
reactLifecycleEndSubject.next();
reactLifecycleEndSubject.complete();
}, [reactLifecycleEndSubject]);
return reactLifecycleEndSubject;
}
const useLifecycleAwareObservable = <
TOutput,
TInputs extends Readonly<any[]>,
TObservable extends Observable<TOutput>,
>(
init: (inputs$: Observable<[...TInputs]>) => TObservable,
inputs: [...TInputs],
): TObservable => {
const lifecycleEnd$ = useReactLifecycleObservable();
return useObservable<TOutput, TInputs, TObservable>(
(inputs$) => {
return init(inputs$.pipe(takeUntil(lifecycleEnd$)));
},
inputs
);
}; |
Root cause:
When using operators like
shareReplay()
, they typically rely on the source observable(i.e. theBehaviorSubject
insideuseObservable()
) to send acomplete
signal in order to unsubscribe the internalReplaySubject
from it. If nocomplete
signal is received, resource leaks could occur.Stackblitz URL: https://stackblitz.com/edit/stackblitz-starters-ghtjf1?devToolsHeight=33&file=src%2FApp.tsx
The example above is using RxJS 6. Haven't tested on RxJS 7 yet.
FantasyGauge
.FantasyGauge
we use a modified version ofuseObservable
withmyShareReplay
(which just logs some actions on top of originalshareReplay
logics from RxJS 6.2.1).FantasyGauge
is destroyed, the BehaviorSubject ofmyUseObservable
still holds someobservers
. See BEFORE.mp4 below.inputs$.complete()
, the BehaviorSubject no longer holds anyobservers
. See AFTER.mp4 below.I also find that
useObservableRef
anduseObservableCallback
both useBehaviorSubject
orSubject
under the hood, and both of them don't seem to callcomplete()
either. So I suspect these hooks might also be vulnerable to resource leaks.BEFORE.mp4
AFTER.mp4
The text was updated successfully, but these errors were encountered: