Skip to content

Commit 253ef8d

Browse files
authored
[2025-06-09] Czy wiesz, do czego służy untracked w Angular? (#269)
1 parent 03f8b81 commit 253ef8d

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
layout: post
3+
title: "Czy wiesz, do czego służy untracked w Angular?"
4+
description: ""
5+
date: 2025-08-01T00:00:00+01:00
6+
published: true
7+
didyouknow: true
8+
lang: pl
9+
author: dmejer
10+
image: /assets/img/posts/2025-06-09-angular-untracked/thumbnail.webp
11+
tags:
12+
- angular
13+
---
14+
15+
W bibliotekach opartych na reaktywnych sygnałach, takich jak Angular Signals,
16+
każda zmiana wartości sygnału używanego w funkcjach `computed()` lub `effect()` powoduje automatyczną rekalkulację lub ponowne wykonanie efektu.
17+
Dzięki temu aplikacja utrzymuje spójny stan i dynamicznie reaguje na zmiany danych.
18+
W niektórych sytuacjach jednak warto pobrać wartość sygnału bez uruchamiania reakcji.
19+
Można to osiągnąć za pomocą funkcji `untracked()`, która pozwala na odczyt wartości sygnału z pominięciem mechanizmu śledzenia zależności.
20+
21+
```typescript
22+
const signalA = signal(0);
23+
const signalB = signal(1);
24+
25+
effect(() => {
26+
console.log(signalA(), untracked(() => signalB()));
27+
})
28+
```
29+
Powyższy kod wykona się ponownie tylko w przypadku aktualizacji wartości sygnału A.
30+
31+
W poniższym przykładzie `untracked` został użyty w komponencie karuzeli kategorii:
32+
```typescript
33+
@Component({
34+
// (...)
35+
template: `
36+
<ul>
37+
@for (category of categories(); track $index; let i = $index) {
38+
<li [attr.row-id]="i" #category>
39+
{{category}}
40+
</li>
41+
}
42+
</ul>
43+
`,
44+
})
45+
export class Categories {
46+
// lista kategorii
47+
categories: WritableSignal<string[]> = signal([
48+
'wszystkie',
49+
'ankieta',
50+
'bezpieczenstwo',
51+
'inne',
52+
'marketing',
53+
'monitoring',
54+
'oferta',
55+
'oplaty',
56+
'oprocentowanie',
57+
'regulaminy',
58+
'reklamacje',
59+
]);
60+
61+
// wybrana kategoria
62+
selectedRow: WritableSignal<number> = signal(0);
63+
64+
}
65+
```
66+
Na karuzeli wyświetlają się poziomo kategorie, które są scrollowalne.
67+
68+
Dodanie scrollowania do wybranej kategorii, można dodać w ramach `effect()`:
69+
```typescript
70+
// (...)
71+
export class Categories {
72+
// (...)
73+
viewChildrenCategories: Signal<ReadonlyArray<ElementRef>> =
74+
viewChildren<ElementRef>('category');
75+
76+
constructor() {
77+
effect(() => {
78+
const selectedRow = this.selectedRow();
79+
const selectedElement = untracked(() =>
80+
this.viewChildrenCategories().find(
81+
(element) =>
82+
element.nativeElement.getAttribute('row-id') == selectedRow
83+
)
84+
);
85+
selectedElement?.nativeElement.scrollIntoView({
86+
behavior: 'smooth',
87+
inline: 'center',
88+
});
89+
});
90+
}
91+
// (...)
92+
}
93+
```
94+
95+
Scroll zostanie wykonany jedynie w przypadku gdy `selectedRow` zostanie zaktualizowany. Aktualizacja kategorii nie spowoduje przeskrollowania.
96+
97+
## Przydatne linki
98+
- [Playground](https://stackblitz.com/edit/stackblitz-starters-1g2ydxbm?file=src%2Fmain.ts)
99+
- [Dokumentacja](https://angular.dev/guide/signals#reading-without-tracking-dependencies)
10.5 KB
Loading

0 commit comments

Comments
 (0)