0

I'm still trying to learn ngrx - the store is set-up and everything seems to work fine. The database I'm using is SQL so basically I'm "clongin" the tables and load them into the store but have problems joining the state in the end when selecting an employee.

The employee entity looks something like this:

export class Employee = {
  id: number;
  firstName: string;
  lastName: string;
  degreeId?: number;
  degree: Degree;
}

export class Degree = {
  id: number;
  description: string;
}

Now in my component, I'd like to get the specific employee to display like this:

{
  id: 1,
  firstName: George,
  lastName: Costanza,
  degreeId: 2,
  degree: {
    id: 2,
    description: 'College'
  }
}

What I tried is to create a selector that merges these two entities:

export const getEmployeeWithAllData = createSelector(
  getSelectedEmployee,
  getRelationalData,
  (employee, data) => {
    const employeesDegree = degree[employee.degreeId]
    employee.degree = employeesDegree

    return employee;
  }
);

This does seem to work if I don't use ngrx-store-freeze - so since I don't know if I am creating the selector correctly or if ngrx-store-freeze has a bug I'm asking this question.

Am I really mutating state when I do this?

If yes, how can I select a specific employee from my store with all the relational data that he has?

What I'm doing doesn't really feel right. In my actual application the employee has about 8 fields of relational data which I need to join...

Edit: I forgot to include the error ngrx-store-freeze throws:

ERROR TypeError: Cannot assign to read only property 'degree' of object '[object Object]'
at eval (employee.selector.ts:85)
at eval (store.es5.js:602)
at memoized (store.es5.js:539)
at defaultStateFn (store.es5.js:573)
at eval (store.es5.js:605)
at MapSubscriber.memoized [as project] (store.es5.js:539)
at MapSubscriber._next (map.js:79)
at MapSubscriber.Subscriber.next (Subscriber.js:95)
at MapSubscriber._next (map.js:85)
at MapSubscriber.Subscriber.next (Subscriber.js:95)
rawk
  • 508
  • 1
  • 7
  • 13
  • 1
    Yes you are mutating state when trying to assign to `employee.degree`. There are a few ways to resolve this. First being doing the inverse, set the degree on the employee *before* it hits the store. Second is using a wrapper object from your selector such as { employee, degree }. – bc1105 Apr 20 '18 at 14:14
  • Thanks! Got it working with the wrapper object :) – rawk Apr 20 '18 at 14:57

1 Answers1

0

yes, you are trying to mutate the state. You can prevent this simply like bellow

export const getEmployeeWithAllData = createSelector(
  getSelectedEmployee,
  getRelationalData,
  (employee, data) => {
    const emp = JSON.parse(JSON.stringify(employee)
    emp.degree = degree[employee.degreeId]

    return emp;
  }
)
Ajantha Bandara
  • 1,473
  • 15
  • 36
  • Had the same idea to solve it like this, but it caused some (in my opinion) buggy behaviour. By returning a deep copy from the selector it caused NgRx to trigger publish events on subscribers to this selector when an effect with that same object was triggered (even though the effect did not change the state). Did you use this solution in a similar complex setup and can confirm, that you did not have this buggy behaviour? – Recek Aug 08 '19 at 13:58