Search code examples
javascriptangulartypescriptngrxngrx-entity

The entity passed to the `selectId` implementation returned undefined


i want to set token and refresh token in ngrx and save and use that for every request and when the page was reload not delete data in redux .

i implementation this state for this :

i dispatch data :

            this.getUserInformation().toPromise().then(responset => {
            if (response.success === true) {
                this.store.dispatch(new SetUserInformation({
                    displayName: responset['result']['displayName'],
                    userInfo: responset.result.claims,
                    RefreshTokenStatus:false,
                    accessToken:response['result']['access_token'],
                    refreshToken:response['result']['refresh_token']
                }))
            }
        });

in module i definde store :

    StoreModule.forFeature('Information', reducer),
    EffectsModule.forFeature([])

this is my reducer :

   const initialState = adapter.getInitialState({
    accessToken: null,
    refreshToken: null,
    RefreshTokenStatus: false,
    userInfo: null,
    displayName: null
})

export function reducer(state = initialState, action: TokenAction): TokenState {

    switch (action.type) {
        case TokenActionTypes.UserInformation:
            return adapter.addOne(action.payload, state)
        default:
            return state;
    }
}

and this is my model :

  export interface TokenState {
    accessToken: string;
    refreshToken: string;
    RefreshTokenStatus: boolean;
    userInfo: string[];
    displayName: string;
}

this is my Selector:

export interface State extends fromState.State, EntityState<TokenState> {
    UserInfo: TokenState;
}

export const adapter: EntityAdapter<TokenState> = createEntityAdapter<TokenState>();
const getTokenFetureState = createFeatureSelector<TokenState>('Information');


export const getAccessToken=createSelector(
    getTokenFetureState,
    state => state.accessToken
)

this is action :

   export class SetUserInformation implements Action {
    readonly type = TokenActionTypes.UserInformation;

    constructor(public payload: TokenState) {
    }
}

export type TokenAction = SetUserInformation

now i have tow problem :

 this.store.pipe(select(fromTokenSelect.getAccessToken)).subscribe(data=>{
     console.log(data)
 })

A: when i want to get token for use that it return null and show me this error :

@ngrx/entity: The entity passed to the selectId implementation returned undefined. You should probably provide your own selectId implementation. The entity that was passed: Object The selectId implementation: (instance) => instance.id

B: when reload the page it delete data from ngrx.

how can i solve this problem ?

enter image description here


Solution

  • You are using ngrx/entity for non-entity data. Entity is designed to work with arrays of data, where each element has some kind of unique identifier. That is why it is throwing the error: you're feeding it non-entity-compatible data. You need to write a simple reducer which simply sets the state, not one which tries to add data to a non-existent entity.

    As for page reload, NgRx will always reset the data, that is the expected behavior. You need to implement localStorage saving if you want to persist data over time.