3

I created two selectors

  1. To get all networks - export const getAllNetworks = createSelector(getState, state => state.networks);

  2. get devices for each network

      createSelector(getAllNetworks, network => {
        const selectedNetwork = network.filter(net => net.id === networkId);
        return selectedNetwork[0]?.allDevices;
      });
    
    

I wanted to create a third selector which uses the first selector to get networks and then uses the second selector to get additional data

export const something = createSelector(
  getAllNetworks, (networks) => {
    networks.map(

      // How can I call the selector selectNetworkDevices by passing the network ID here and get the devices [ex: selectNetworkDevices(network.id)]

    )
  }
)
kireeti9
  • 228
  • 3
  • 6
  • aren't you getting an error in your 2nd selector? how does it get the networkId? – Andres2142 Jun 05 '22 at 01:24
  • @Andres2142 getAllNetworks - would give me an array of network objects which has an id property on each of them. the first and second selectors are just examples. all I am trying to do is to call another selector inside a create selector (the third one) – kireeti9 Jun 05 '22 at 02:19

1 Answers1

2

You can use different selectors based on others like this:

export const selectUsers = createSelector(getState, (state) => state.users);

export const selectAccounts = (accountId?: string) => 
 createSelector(getState, (state) => 
   accountId ? state.accounts[accountId] : {}
 );

export const something = (accountId?: string) => 
  createSelector(
    selectUsers,
    selectAccounts(accountId),
    (usersData, accountsData) => {
      // some logic
      return accountId ? 'an account id was provided' : 'no-id'
    }
  )

In your component you could call this selector either providing the parameter or not:

ngOnInit(): void {
  this.store.select(something());  // without parameter
  this.store.select(something('anAccountId')); // with parameter
}

More information here: link

UPDATE:

We have 2 selectors, selectAccounts and myOtherSelector. For myOtherSelector, instead of calling directly the selectAccounts selector, you can reuse its logic by calling its callback function.

export const selectUsers = createSelector(getState, (state) => state.users);

export const selectAccounts = (accountId?: string) => 
 createSelector(getState, (state) => filterAccount(state));

export const myOtherSelector = createSelector(
  selectUsers,
  (users) => {
    if (users) return users;

    // here, you are reusing the callback function related to
    // another selector
    const accountFiltered = filterAccount([]);
    return accountFiltered;
  }
)

function filterAccount(accounts): Account {
 //...some complex logic 
 // ...
 // ...
 return account[index];
}
Andres2142
  • 2,622
  • 2
  • 14
  • 19
  • Let me clarify my question once again, There are two selectors you mentioned, one is **selectAllNetworks** and second one is **selectAllDevicesById** Now I would like to create a new selector – kireeti9 Jun 05 '22 at 04:25
  • `export const newSelector = createSelector(selectAllNetworks, (networks) => { networks.forEach( (network) => { //want to do some business logic here and at some point I wanted to get the devices for each network and I want to use the second selector selectAllNetworks // How do I call the second selector here selectAllNetworks(network.id) // This is returning a memoized function but not the devices } ) })` You can ask me why do you need to use the second selector to get devices, you can just do network.devices, This is just a example use case I mentiond – kireeti9 Jun 05 '22 at 04:46
  • The above is just an example use case, my main question is, How do I call another selector in the create selector. – kireeti9 Jun 05 '22 at 04:47
  • I understood this one @Andres2142. what if the second selector takes a id as a input parameter. – kireeti9 Jun 05 '22 at 05:03
  • If the second selector is this one, `export const selectAccountsOfUsers = (id: string) => createSelector( selectUsers, (users) => { const user = users.find((usr) => usr.id === id); return user?.accounts; })` Then How can we use both the selectors without passing the ID – kireeti9 Jun 05 '22 at 05:06
  • Sorry @Andres2142, Let me explain my question again. There is one selector [ ** selector 1 ** ]which takes input (id) as a parameter and returns some value, I have one more selector [ ** Selector 2 **] created using create selector and in its projector, I would like to call the selector1 and pass the id parameter to get some value. I was expecting the call would return some value, but the selector 1 call is returning a memoized function. – kireeti9 Jun 05 '22 at 06:31
  • Andres2142 - Any suggestions on how to achieve it? – kireeti9 Jun 06 '22 at 06:33
  • @kireeti9, I hope this last updated I did solves your issue – Andres2142 Jun 07 '22 at 02:13