Skip to content
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

[feature request] trackedIf util #501

Open
MillerSvt opened this issue Sep 18, 2024 · 2 comments
Open

[feature request] trackedIf util #501

MillerSvt opened this issue Sep 18, 2024 · 2 comments

Comments

@MillerSvt
Copy link
Contributor

Hi. We often need to track signals only until they reach the desired value. For example, send an analytics event when the page load completes, and don't send any more analytics events when the user loads something inside the page after the initial load.

I suggest adding the trackedIf utility, which will track the signal only up to a certain value.

Expected API:

isLoading = signal(true);

effect(() => {
  if (trackedIf(isLoading, value => value)) {
    return;
  }
  sendAnalytic();
});
someCondition = signal(true);
isLoading = signal(true);

effect(() => {
  if (!someCondition() || trackedIf(isLoading, value => value)) { // always track someCondition, track isLoading only if it is truthy
    return;
  }
  sendAnalytic();
});

Realization:

import type {Signal} from '@angular/core';
import {untracked} from '@angular/core';

export function trackedIf<T>(signal: Signal<T>, condition: (value: T) => boolean): T {
    const value = untracked(signal);

    if (condition(value)) {
        signal();
    }

    return value;
}
@jdegand
Copy link
Contributor

jdegand commented Sep 19, 2024

Once the signal is untracked, should it be destroyed or cleaned up?

@MillerSvt
Copy link
Contributor Author

MillerSvt commented Sep 19, 2024

Once the signal is untracked, should it be destroyed or cleaned up?

I think it is unnecessary. Because if there are no signals tracked, the effect will not execute at all.
And the common case of using these utilities is to track one or more signals conditionally (not all). So at least one tracked signal should be present.

This is analog of takeWhile, or filter + take(1) operator in rxjs:

mainThread$.pipe(
  switchMap(value => childThread.pipe(
    filter(childValue => childValue === 'foo'),
    take(1),
  ),
).subscribe(() => doStuff())

effect(() => {
  const main = mainSignal();
  const child = trackedIf(childSignal, value => value !== 'foo');
  if (main && child === 'foo') {
    doStuff();
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants