ngrx 无状态组件 + 与商店交互 [英] ngrx stateless components + interacting with store

查看:43
本文介绍了ngrx 无状态组件 + 与商店交互的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以编写与 ngrxs 存储交互的无状态组件?

几乎所有我见过的例子都没有使用@Input 来为组件提供状态,而是使用组件内的 this 上下文来使用选择器检索状态,根据定义,这使得组件有状态.

我不相信 ngrx 中有任何等效的 mapStateToProps,它允许与商店的无状态交互..

解决方案

我举个例子.

假设您在应用程序中有一个方面负责显示待售产品.

products.component.ts(有状态组件)

product$ = this.store.select(getProducts);所选产品:IProduct;构造函数(私有商店:Store){}setSelectedProduct(产品:IProduct){this.selectedProduct = 产品;}

products.component.html

<精选产品[产品]=选定产品"></selected-product>

product-details.component.ts(无状态,负责监听点击产品并发出点击了哪个项目)

@Input() 产品:IProduct;@Output() productSelected = new EventEmitter();onProductSelect() {this.productSelected.emit(this.product);}

product-details.component.html

<div>{{product.id }}</div><div>{{product.name }}</div>

selected-product.component.ts(负责在底部显示点击的产品)

@Input() 产品:IProduct;

selected-product.component.html

因此,我们的想法是制作与您的应用程序相关的功能切片,其中一个组件是有状态组件(知道如何与商店对话),即 products.component.ts.其他每个视图都会获取输入的数据.

这并不能解决道具钻取的问题,但它会使单元测试具有@Input() 和@Output()(无状态组件)的组件变得容易.

我在 React 中也使用这种方法,在那里我有一个有状态的组件(使用 mapDispatchToProps 和 mapStateToProps),然后我将属性作为 props 向下传递,使单元测试更容易.

我不会考虑在 React 无状态中使用 mapStateToProps 的子组件,因为它们仍然必须知道如何从存储中读取,并且为此编写单元测试也很困难,因为您将有在做单元测试时模拟商店或给商店.

这个propDrilling的另一个好处是一个组件负责从store中读取,如果store的结构发生变化,代码更改必须在一个组件中完成,属性会像以前一样向下流动.但是随着每个子组件都有 mapStateToProps 的方法,商店结构的变化会在每个有 mapStateToProps 的地方完成.

如果你想在多个地方使用 this.store.select() ,那也很好,但它等价于 mapStateToProps 在多个地方.基本上,如果您可以按照概述进行道具钻探,那么单元测试和重构会更容易.

is it possible to write stateless components that interact with ngrxs store?

almost all the examples i've seen do not use @Input to provide state to components, but instead use the this context inside a component to retrieve state with a selector, which by definition makes the component stateful.

i don't believe there is any equivalent of mapStateToProps in ngrx, which would allow stateless interaction with a store..

解决方案

I will give you an example.

Say you have an aspect in the application that is responsible for displaying the products for sale.

products.component.ts (stateful component)

product$ = this.store.select(getProducts);
selectedProduct: IProduct;
constructor(private store: Store<ProductsState>) { }

setSelectedProduct(product: IProduct) {
  this.selectedProduct = product;
}

products.component.html

<product-details *ngFor="let product of products$ | async"
   [product]="product"
   (productSelected)="setSelectedProduct($event)"
></product-details>
<div class="selected-product" *ngIf="selectedProduct">
  <selected-product
    [product]="selectedProduct"
  ></selected-product>
</div>

product-details.component.ts (stateless, responsible for listening to click on product and emitting which item got clicked on)

@Input() product: IProduct;
@Output() productSelected = new EventEmitter<IProduct>();

onProductSelect() {
  this.productSelected.emit(this.product);
}

product-details.component.html

<div (click)="onProductSelect()">
  <div>{{ product.id }}</div>
  <div>{{ product.name }}</div>
</div>

selected-product.component.ts (responsible for showing the clicked on product at the bottom)

@Input() product: IProduct;

selected-product.component.html

<img src="product.img" alt="product image" />
<div class="rating">{{product.rating}}</div>
<div *ngFor="let comment of product.reviewComments"> {{ comment }}</div>

So the idea is to make a feature slice related to your application and one component would be the stateful component (knows how to talk to the store) which is products.component.ts. Every other view gets the data inputted to it.

This doesn't solve the issue of prop drilling but it will make unit testing the components that have @Input() and @Output() (stateless components) easy.

I use this approach in React as well where I have one stateful component (with mapDispatchToProps and mapStateToProps) and then I pass the properties down as props making unit tests easier.

I wouldn't consider child components with mapStateToProps in React stateless either because they still have to know how to read from the store and writing unit tests for this will be difficult as well because you would have to mock the store or give the store when doing unit tests.

Another advantage of this prop drilling is that one component is responsible for reading from the store and if the structure of the store changes, the code change has to be done in one component and the properties will be flowing down just like before. But with the approach of each child component having mapStateToProps, the change of the structure of the store would have be done in each place that has mapStateToProps.

If you want to have this.store.select() in multiple places, that's fine as well but that's equivalent to mapStateToProps in multiple places. Basically, if you can do prop drilling as outlined, unit testing and refactoring would be easier.

这篇关于ngrx 无状态组件 + 与商店交互的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆