Search code examples
reduxngxs

NGXS: Can we split out an object from array into a substate?


My top level state model looks like this:

{
    listOfItems: [],    // Item[]
    selections: {
        itemId: 0
    }
}

The items list may contain 10 different shopping items. When the user clicks on an item, it updates the selection, and my @Selector will rerun.

Action: Set Item Selection

  @Action(Item.Select)
  setState(
    { setState }: StateContext<ItemsModel>,
    { itemId }: Item.Select
  ) {
    setState(patch({ selections: patch({ itemId }) }));
  }

Selector: Select Current Item

@Selector()
static getSelectedItem(state: ItemModel): Item {
    return state.itemList.find(i => i.itemId === state.selections.itemId);
}

Problem is: I have up to 20 actions to perform on the selected Item. This results in:

  1. Lots of .find() lookups to find item in the original array (both selector and actions)
  2. Actions to perform on the listOfItems are in the same place as those to perform on a specific Item

I would like to: Keep the array and selection in this state, but separate out the "selected item" into a new substate, where the child state's model can just be Item type. This way I can encapsulate all the actions on Item in a different place to actions on the Items[] array.

I'm not sure how to keep them in sync. I need to keep the 'selectedItem' state up to date when the selection itemId changes in the parent. I also need to make sure any mutations to the selectedItem are reflected in the original array in the parent.


Solution

  • This seems like it might be more of a fundamental problem with how you are trying to represent your application state. Have you thought of normalizing your list of items? Or at least using a key/value lookup object instead of an array? You wouldn't need to use the .find() to do your lookup and could access the key of the object via the unique id you are interested in. Let me know if that is of any help!