1

I'm creating a people reducer...

However, we know that requests may very well fail and that is why I inserted in getInitialState() some properties such as data, error and loading.

The data is an object of type People to be able to enter the values โ€‹โ€‹of the specific person.

The error is an object of type RequestError if an error occurs in the request.

Finally, loading is the loading of requests.

The error that occurs is that it says that the RequestError interface is not signed in the People interface, which is obvious, because I am using the state as a base.

enter image description here

How do I do this implementation?

ERROR:

var error: RequestError
Argument of type 'RequestError' is not assignable to parameter of type 'People'.
  Type 'RequestError' is missing the following properties from type 'People': id, isMain, avatar, messagests(2345)

ACTIONS:

import { createAction, props } from '@ngrx/store';
import { RequestError } from '@shared/interfaces/request.interface';
import { People } from '@shared/interfaces/people.interface';

export const GET = createAction('[GET: USER/API] Get a people');

export const CREATE = createAction('[POST: USER/API] Create a new people', props<{ data: People }>());
export const CREATE_SUCCESS = createAction('[POST: USER/API] Successfully created person', props<{ data: People }>());
export const CREATE_FAIL = createAction('[POST: USER/API] Failed to create a new person', props<{ error: RequestError }>());

export const UPDATE = createAction('[PUT: USER/API] Update a people', props<{ id: string; changes: Partial<People> }>());
export const UPDATE_SUCCESS = createAction('[PUT: USER/API] Person updated with success', props<{ id: string; changes: Partial<People> }>());
export const UPDATE_FAIL = createAction('[PUT: USER/API] Person update failed', props<{ error: RequestError }>());

REDUCER:

import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { Action, createReducer, on } from '@ngrx/store';
import { People } from '@shared/interfaces/people.interface';
import * as fromPeopleAction from './people.actions';

export interface State extends EntityState<People> {}

export const adapter: EntityAdapter<People> = createEntityAdapter<People>({
    selectId: (people: People) => people.id,
});

const INIT_STATE: State = adapter.getInitialState({
    data: null,
    error: null,
    loading: false,
});

const peopleReducer = createReducer(
    INIT_STATE,
    on(fromPeopleAction.CREATE, (state: State, { data }) => adapter.addOne(data, { ...state, loading: true })),
    on(fromPeopleAction.CREATE_SUCCESS, (state: State, { data }) => adapter.addOne(data, { ...state, loading: false })),
    on(fromPeopleAction.CREATE_FAIL, (state: State, { error }) => adapter.addOne(error, { ...state, loading: false }))
);

export function reducer(state: State | undefined, action: Action) {
    return peopleReducer(state, action);
}
  • Can you have a look at Redux DevTools and check if in a successful `People` creation action, `data` remains null? If you can share the state Tree would be good also. โ€“ Max Amorim Apr 23 '20 at 11:00
  • Inserted the chart! โ€“  Apr 23 '20 at 12:35

1 Answers1

0

As your chart shows, data property from State remains null, even when your CREATE action is successful, which means that the issue is with your action's props. Since your EntityAdapter is of type People, when you call the function adapter.addOne(), it is expecting params from type People. The way you modeled your State, data, error and loading are People's properties, which means that when you want to add or update any property, you need to wrap it inside of People class.

In summary you would have to change your CREATE_FAIL action's props to something similar as:

props<{ people: { error: RequestError } }>()

Or when you call adapter.addOne(), wrap it.

In case you already have the people state created on store and want to add an error, you can call adapter.updateOne() instead of addOne().

Max Amorim
  • 147
  • 1
  • 13