#angular
Вопрос:
Проблема ngrx в том, что внутри тела селектора переменной в классе присваивается значение, но оно не может использоваться вне тела селектора
Компонент.ts
export class ProfileComponent implements OnInit {
@Input() loading: boolean=false;
Profile= {} as Profile;
user = {} as User;
data:any
constructor(private store: Store<AppState>,
private spinner: NgxSpinnerService) {
this.store.select(getUser).subscribe((data:any)=>this.user=data);
this.store.select(getloadingProfile).subscribe(data=>{
this.spinner.show();
if(!data){
this.loading=data;
this.spinner.hide();
}});
}
ngOnInit() {
this.store.select(getloadingProfile).subscribe((dataProfile:any)=> {
this.Profile=dataProfile;
console.log(this.Profile); //<--Here it prints the data inside the selector body
});
console.log(this.Profile); //<--here does not print
}
}
это:
селектор.ts
import { ProfileState } from '../state/Profile.state';
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { selectAll } from '../reducers/Profile.reducers';
export const Profile_STATE_NAME = 'Profile';
const getProfileState = createFeatureSelector<ProfileState>(Profile_STATE_NAME);
export const getProfile = createSelector(getProfileState, selectAll);
export const getProfileEntities = createSelector(
getProfileState,
(state) => state.Profile
);
export const getloadingProfile = createSelector(getProfileState, (state) => state.ProfileLoaded);
export const selectProfileError = createSelector(getProfileState, (state) => state.error);
это:
Действие.ts
import { EntityState, createEntityAdapter, EntityAdapter } from '@ngrx/entity';
import { ProfileModule } from 'src/app/profile/profile.module';
import { Profile } from '../../models/Profile.model';
export interface ProfileState extends EntityState<Profile> {
ProfileLoaded: boolean;
Profile:Profile;
error: boolean;
}
export const ProfileAdapter: EntityAdapter<Profile> = createEntityAdapter<Profile>({
selectId: (customer: Profile) => customer.id
});
export const initialState: ProfileState = ProfileAdapter.getInitialState({
ProfileLoaded: true,
error: false,
Profile:{} as Profile
});
это:
состояние.ts
import { EntityState, createEntityAdapter, EntityAdapter } from '@ngrx/entity';
import { ProfileModule } from 'src/app/profile/profile.module';
import { Profile } from '../../models/Profile.model';
export interface ProfileState extends EntityState<Profile> {
ProfileLoaded: boolean;
Profile:Profile;
error: boolean;
}
export const ProfileAdapter: EntityAdapter<Profile> = createEntityAdapter<Profile>({
selectId: (customer: Profile) => customer.id
});
export const initialState: ProfileState = ProfileAdapter.getInitialState({
ProfileLoaded: true,
error: false,
Profile:{} as Profile
});
this is:
reducer.ts
import {loadProfileSuccess,loadProfileFail,} from '../actions/Profile.actions';
import { createReducer, on } from '@ngrx/store';
import { initialState, ProfileAdapter } from '../state/Profile.state';
const _ProfileReducer = createReducer(
initialState,
on(loadProfileSuccess, (state, action) => ({
...state,
Profile:action.profile,
ProfileLoaded: false
})),
on(loadProfileFail, (state) => {
return ProfileAdapter.removeAll({
...state,
error: true,
loading: false,
});
}),
);
export const { selectAll, selectIds } = ProfileAdapter.getSelectors();
export function ProfileReducer(state:any, action:any) {
return _ProfileReducer(state, action);
}
это:
Эффект.ts
@Injectable()
export class ProfileEffects {
constructor(
private actions$: Actions,
private PagesService: PagesService,
) { }
loadProfile$ = createEffect(() =>
this.actions$.pipe(
ofType(loadProfile),
concatMap(() => this.PagesService.GetProfile()),
map((Profile:Profile) => {
return loadProfileSuccess({ profile:Profile })
},
catchError((error) => of(loadProfileFail(error))))
)
);
}
это:
решатель.ts
@Injectable()
export class ProfileResolver implements Resolve<Observable<any>> {
constructor(private store: Store<AppState>) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
return this.store
.pipe(
select(getloadingProfile),
tap((loadProfileSuccess) => {
if (loadProfileSuccess) {
console.log(loadProfileSuccess);
this.store.dispatch(loadProfile());
}
}),
first()
);
}
}
Пожалуйста, помогите мне как можно скорее, спасибо
Комментарии:
1. Похоже, вы пытаетесь напечатать значение
this.Profile
до того, как ему будет присвоено значение. Можете ли вы попробовать распечатать его значение в крючке жизненного цикла ngAfterViewInit ()?2. Наблюдаемый ваш селектор выдает события асинхронно, это означает, что ваш обратный вызов подписки не вызывается немедленно. В то время, когда вы попытаетесь распечатать свою переменную, которая на данный момент все еще не инициализирована, вы увидите пустой объект.
3. @Phalgun Он по-прежнему печатает пустое значение после того, как попробовал то, что вы сказали
4. @RomanP. Каково, пожалуйста, решение?
5. Для этого существует множество решений, одно из которых вы можете увидеть в моем ответе.
Ответ №1:
Если вы введете начальное состояние профиля с нулем, вы можете сделать что-то подобное:
this.store.select(getloadingProfile).pipe(
filter(Boolean),
take(1),
).subscribe((profile) => console.log('Your Profile', profile));
Что бы подписаться на ваш observable, отфильтруйте начальное значение до тех пор, пока оно не будет инициализировано чем-то правдивым, затем оно примет первое излучение, распечатает его на консоли и отпишется.
Каждый раз, когда вы подписываетесь на наблюдаемое, вы также должны отказаться от подписки на него.
В первом примере оператор take откажется от подписки за вас.
Но я бы посоветовал вам работать с наблюдаемым в вашем шаблоне с помощью асинхронного канала, это позволит вам подписаться / отказаться от подписки.
напр.:
<div *ngIf="ProfileObs$ | async as profile">
<span>Name: {{ profile.name }}</span>
</div>
Комментарии:
1. Он по-прежнему не работает для обновления новых значений, но в шаблоне он отображает значения, но я не могу выполнить какую-либо операцию с предстоящими данными, потому что он дает нулевые значения. Есть ли какое-то решение? Я знаю, что устал от тебя
2. Какие ценности вы имеете в виду? Ваши локальные переменные вашего класса? Отправляете ли вы действие, которое вызывает ваш эффект? Есть ли правильные данные в вашем штате? Пример СтекбЛитца был бы хорош.
3. Спасибо, проблема решена. Проблема заключалась в том, что я использовал canActivate с решателем. Он был удален, может быть активирован, так как ему было разрешено перейти в компонент перед загрузкой данных профиля