I am currently dispatching an event to retrieve all data from the backend, and with this dispatch I popularize the state copy.
So far so good, the problem is if there is nothing on the backend that I would need to dispatch an event to create the data on it and in a new copy of the state.
For this I used a selector to check if there is already something in the state, because if there is one there will be in the backend, his problem is that the result arrives multiple and the delay is the same as in the image below:
APP COMPONENT
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
title = 'webwhatsapp';
protected peoples: Array<IPeople> = [
{ id: '0', isMain: true, name: 'THIAGO DE BONIS CARVALHO SAAD SAUD', avatar: 'assets/users/thiagobonis.jpg', messages: null },
{ id: '1', isMain: false, name: 'BILL GATES', avatar: 'assets/users/billgates.jpg', messages: null },
{ id: '2', isMain: false, name: 'STEVE JOBS', avatar: 'assets/users/stevejobs.jpg', messages: null },
{ id: '3', isMain: false, name: 'LINUS TORVALDS', avatar: 'assets/users/linustorvalds.jpg', messages: null },
{ id: '4', isMain: false, name: 'EDSGER DIJKSTRA', avatar: 'assets/users/dijkstra.jpg', messages: null },
];
constructor(private readonly peopleDispatchService: PeopleDispatchService, private readonly peopleSelectorsService: PeopleSelectorsService) {}
ngOnInit(): void {
this.peopleDispatchService.getAll();
this.peopleSelectorsService.total.subscribe((total) => {
console.log(total);
if (total === 0) {
// this.peoples.forEach((people) => this.peopleDispatchService.create(people));
} else {
}
});
}
}
REDUCERS
export interface State extends EntityState<IPeople> {
error: IRequestError | null;
loading: boolean;
}
export const adapter: EntityAdapter<IPeople> = createEntityAdapter<IPeople>({
selectId: (people) => people.id,
});
const INIT_STATE: State = adapter.getInitialState({
error: null,
loading: true,
});
const peopleReducer = createReducer(
INIT_STATE,
on(fromPeopleAction.GET_ALL_SUCCESS, (state, { peoples }) => adapter.addMany(peoples, { ...state, loading: false })),
on(fromPeopleAction.GET_ALL_FAIL, (state, { error }) => ({ ...state, error, loading: false })),
on(fromPeopleAction.CREATE_SUCCESS, (state, { people }) => adapter.addOne(people, { ...state, loading: false })),
on(fromPeopleAction.CREATE_FAIL, (state, { error }) => ({ ...state, error, loading: false })),
on(fromPeopleAction.DELETE_SUCCESS, (state, { id }) => adapter.removeOne(id, { ...state, loading: false })),
on(fromPeopleAction.DELETE_FAIL, (state, { error }) => ({ ...state, error, loading: false }))
);
export function reducer(state: State | undefined, action: Action) {
return peopleReducer(state, action);
}
EFFECTS
@Injectable()
export class Effects {
constructor(private action$: Actions, private backend: BackendService, private requestHandler: RequestHandlerService) {}
getAll$ = createEffect(() =>
this.action$.pipe(
ofType(fromPeopleActions.GET_ALL),
mergeMap(() => {
return this.backend.getAll().pipe(
map((peoples) => fromPeopleActions.GET_ALL_SUCCESS({ peoples })),
catchError((error) => of(fromPeopleActions.GET_ALL_FAIL({ error: this.requestHandler.getError(error) })))
);
})
)
);
create$ = createEffect(() =>
this.action$.pipe(
ofType(fromPeopleActions.CREATE),
mergeMap((action) => {
return this.backend.create(action.people).pipe(
map((people) => fromPeopleActions.CREATE_SUCCESS({ people })),
catchError((error) => of(fromPeopleActions.CREATE_FAIL({ error: this.requestHandler.getError(error) })))
);
})
)
);
deleteAll$ = createEffect(() =>
this.action$.pipe(
ofType(fromPeopleActions.DELETE),
mergeMap((action) => {
return this.backend.delete(action.id).pipe(
map(() => fromPeopleActions.DELETE_SUCCESS({ id: action.id })),
catchError((error) => of(fromPeopleActions.DELETE_FAIL({ error: this.requestHandler.getError(error) })))
);
})
)
);
}
SELECTORS
const featureSelector = createFeatureSelector<State>('people');
export const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors(featureSelector);
export const getError = createSelector(featureSelector, (state: State) => state.error);
export const getIsMain = createSelector(featureSelector, (state: State) => {
state.ids.forEach((id: any) => {
if (state.entities[id].isMain) {
return state.entities[id];
}
});
});