NgRx 无法从商店中选择

Posted

技术标签:

【中文标题】NgRx 无法从商店中选择【英文标题】:NgRx can't select from store 【发布时间】:2018-03-25 20:45:05 【问题描述】:

我正在做一个非常简单的 NgRx 实现,现在只是为一个组件做 get。根据 Redux Devtool,数据来自有效负载,但我似乎无法通过异步管道访问它。

开发工具:

---更新----

问题是当我访问我的 ts 文件中的切片时,我得到了错误

“网络”类型的参数不能分配给类型参数 '“开始”'。

ts 文件

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)
                    )
                
            )
    

我的功能模块

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

我的根减速器(我没有任何模块没有延迟加载,所以我的根减速器是空的......不知道如何让它工作)

import  Action  from '@ngrx/store';

export interface State 
    start: string;


const initialState: State = 
    start: ''


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

和我更新的功能缩减器来访问 dns 数组

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;
    

【问题讨论】:

尝试在 getDns() 之外设置 dnsServer = this.store.select('dns') 的定义。如果您使用类型,还要将 dnsServer 的类型设置为 Obseravble。 getDns() 在 ngOninit() 中被调用,所以它是否在外面无关紧要。我最终会输入可观察的,但这并不能解决问题 我想我知道。返回的有效负载对象可能与订阅获取的值不同,然后立即设置。最初可能只是空的,并且 async 什么也得不到,但在调度后会更新。但是,由于期望未定义的 DNS,您会导致它出错。因此,为什么它在没有安全操作员的情况下会失败,但可以在安全的情况下工作。这些值稍后会更新为工作值。如果您将默认状态设置为具有 DNS 和一些假值的对象,它将起作用....试试吧! 【参考方案1】:

在您的构造函数中,store 指的是整个应用程序状态,而不仅仅是network。应该是

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

您需要使用它访问它

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

另外,action.payloaddns: ["6.7.7.7", "5.5.5.5"]。当你在你的减速器中分配它时,你正在做dns: [action.payload],所以你最终会得到NetworkState


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

如果您想在每次需要状态切片时减少构造函数中的逻辑,可以使用选择器:

import  createFeatureSelector, createSelector  from "@ngrx/store";

export const selectNetwork = createFeatureSelector<fromNetwork.NetworkState>('network');
export const selectNetworkDns = createSelector(selectNetwork, (state) => state.dns);

在构造函数中使用它:

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

【讨论】:

我想通了。在我的模块中,我有StoreModule.forFeature('network', dnsReducer) 而不是StoreModule.forFeature('dns', dnsReducer),是的,我传递的是对象而不是列表,所以这也有帮助。我在状态“网络”下有多个减速器,所以我必须弄清楚如何构建它...... 你可以传入一个对象:.forFeature('network', dns: dnsReducer, otherThing: otherThingReducer)。也看看selectors。它将消除在.select() 之后调用.map() 的任何需要,只是为了获得一部分状态。 天哪,你是最棒的,这正是我想要的!但有一件事,你如何从网络切片访问 dns?谢谢!如果你想更新你的答案以包含它,我会把它标记下来 这是一个延迟加载的功能,所以我必须从网络状态访问它 感谢更新!唯一的问题是它是延迟加载的,所以我无法通过主应用程序状态访问它,它扩展了应用程序状态。

以上是关于NgRx 无法从商店中选择的主要内容,如果未能解决你的问题,请参考以下文章

ngrx 商店选择仅订阅特定操作

将变量从商店绑定到角度ngrx中的组件

无法读取未定义(读取“地图”)NGRX 实体的属性

在单元测试中使用参数模拟 ngrx 存储选择器(Angular)

NGRX:如何从其他选择器中调用工厂选择器

@ngrx 在递归使用智能组件时从存储中选择特定的状态片