Search code examples
angularrxjsstorengrx

NgRx can't select from store


I am doing a very simple implementation of NgRx, right now just doing the get for one component. The data comes through in the payload according to the Redux Devtool, but I cant seem to access it through the async pipe.

Devtool:

redux dev tool state redux dev tools image payload

---UPDATE----

the problem is when i access the slice in my ts file, i get the error

Argument of type '"network"' is not assignable to parameter of type '"start"'.

ts file

constructor(private store: Store<fromApp.AppState>) {}
getDns() {
        // reach out to ngrx store
        this.dnsServers$ = this.store.select('network').map(network => network.dns)
        console.log(this.dnsServers$)
        // get current dns IPs'
        this.networkService.getDns()
            .subscribe(
                (dnsList: Dns) => {
                    console.log(dnsList.dns);
                    this.store.dispatch(
                        new LoadIpSuccessAction(dnsList.dns)
                    )
                }
            )
    }

my feature module

StoreModule.forFeature('network', { dns: dnsReducer })

my root reducer (I do not have any modules not loaded lazy, so my root reducer is empty... Not sure how to make it work otherwise)

import { Action } from '@ngrx/store';

export interface State {
    start: string;
}

const initialState: State = {
    start: ''
}

export function startReducer(state = initialState, action: Action) {
    return state;
}

and my updated feature reducer to access the dns array

import * as NetworkActions from './network.actions';
import * as fromApp from '../../store/app.reducers';

export interface NetworkState extends fromApp.AppState {
    dns: DnsState;
}

export interface DnsState {
    dns: string[];
}

const initialState: DnsState = {
    dns: []
}

export function dnsReducer(state = initialState, action: NetworkActions.DnsActions) {
    switch (action.type) {
        case NetworkActions.LOAD_IP_SUCCESS:
            return {
                ...state,
                dns: [...action.payload]
            }
        default:
            return state;
    }
}

Solution

  • In your constructor, store refers to the entire app state, not just network. It should be

    constructor(..., private store: Store<fromApp.AppState>) {}
    

    You'll need to access it using

    this.dnsServers$ = this.store.select('network').map(network => network.dns);
    

    In addition, action.payload is {dns: ["6.7.7.7", "5.5.5.5"]}. When you assign it in your reducer, you are doing dns: [action.payload], so you're ending up with the NetworkState being:

    {
        dns: [
            { dns: ["6.7.7.7", "5.5.5.5"] }
            ]
    }
    

    If you want to reduce the logic in your constructors every time you want a slice of the state, you can use selectors:

    import { createFeatureSelector, createSelector } from "@ngrx/store";
    
    export const selectNetwork = createFeatureSelector<fromNetwork.NetworkState>('network');
    export const selectNetworkDns = createSelector(selectNetwork, (state) => state.dns);
    

    To use it in your constructor:

    constructor(private store: Store<fromApp.AppState>) {
        this.dnsServers$ = this.store.select(selectNetworkDns);
    }