Почему преобразование Observable в WritableSignal в Angular 16 выдает ошибку отсутствия свойств
У меня есть следующий простой код на моем компоненте:
import {Component, effect, signal, WritableSignal} from '@angular/core';
import {AppService} from "../app.service";
import {toSignal} from "@angular/core/rxjs-interop";
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
translations: WritableSignal<{data: {}}> = signal({data: []});
constructor( private appService: AppService) {
this.translations = toSignal(this.appService.getTranslations());
effect(() => {
console.log('translation API:', this.translations());
});
}
changeValue(): void {
this.translations.set({data: {hello: 'hallo'}})
}
}
К вашему сведению:this.appService.getTranslations()
возвращает наблюдаемую
Я пробую новые функции, выпущенные в Angular v16, и то, как конвертировать Observables в сигналы.
Что я хотел сделать в приведенном выше коде, так это изменить значение объекта WritableSignal и зарегистрировать его значение при изменении.
Я получаю следующую ошибку:
TS2739: Type 'Signal ' is missing the following properties from type 'WritableSignal{ data: {}; }>': set, update, mutate, asReadonly
Помоги пожалуйста.
1 ответ
Observables доступны только для чтения и, следовательно, не подходят для . Вы можете подписаться на них, но не вызывать такой метод, какnext
для передачи новых данных.
Потенциально объекты можно преобразовать в , но, насколько мне известно, служебного метода не существует.
Ошибка, которую вы получаете, означает, что у объекта, который возвращается, отсутствуют свойства/методы из, все «записываемые»; это версия «только для чтения»WritableSignal
.
В этом случае вам следует подписаться на свою наблюдаемую и установить сигнал в обратном вызове.
ЕслиAppService
используется скрытно, нет необходимости отписываться, поскольку это делается автоматически при первом успешном обратном вызове.
constructor(private appService: AppService) {
this.appService.getTranslations().subscribe(data => {
this.translations.set(data)
});
effect(() => {
console.log('translation API:', this.translations());
});
}
Если он не используется и вы хотите получить данные только один раз при построении, используйтеfirst()
Оператор RxJS.
constructor(private appService: AppService) {
this.appService.getTranslations().pipe(first()).subscribe(data => {
this.translations.set(data)
});
effect(() => {
console.log('translation API:', this.translations());
});
}
Если он не используетHttpClient
, и вам нужно регулярно получать обновления, вам придется отказаться от подписки на уничтожение.
Поскольку вы тестируете предварительную версию Angular 16 для разработчиков, вы можете использовать новыйDestroyRef
для этого, а не дляOnDestroy.ngOnDestroy
крюк.
constructor(
private appService: AppService,
destroyRef: DestroyRef
) {
const sub = this.appService.getTranslations().subscribe(data => {
this.translations.set(data)
});
destroyRef.onDestroy(() => {
sub.unsubscribe();
});
effect(() => {
console.log('translation API:', this.translations());
});
}
И, наконец, если вы все еще хотите использоватьtoSignal
, твойtranslations
поле должно иметь тип . Но тогда твойchangeValue
метод больше не будет работать, так какSignal
не имеет методаset
.