componentes sem estado ngrx + interação com a loja

Sep 25 2020

é possível escrever componentes sem estado que interagem com o armazenamento ngrxs?

quase todos os exemplos que vi não usam @Input para fornecer estado aos componentes, mas, em vez disso, usam o thiscontexto dentro de um componente para recuperar o estado com um seletor, que por definição torna o componente com estado.

não acredito que exista qualquer equivalente a mapStateToProps em ngrx, que permitiria a interação sem estado com uma loja.

Respostas

1 AliF50 Sep 26 2020 at 04:58

Vou lhe dar um exemplo.

Digamos que você tenha um aspecto no aplicativo que seja responsável por exibir os produtos à venda.

products.component.ts (componente com estado)

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 (sem estado, responsável por ouvir o clique no produto e emitir qual item foi clicado)

@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 (responsável por mostrar o produto clicado na parte inferior)

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

Portanto, a ideia é fazer uma fatia de recurso relacionada ao seu aplicativo e um componente seria o componente stateful (sabe como falar com a loja) que é products.component.ts. Todas as outras visualizações recebem os dados inseridos nela.

Isso não resolve o problema de perfuração de suporte, mas tornará o teste de unidade dos componentes que têm @Input () e @Output () (componentes sem estado) fáceis.

Eu uso essa abordagem no React também, onde tenho um componente stateful (com mapDispatchToProps e mapStateToProps) e, em seguida, passo as propriedades como adereços, facilitando os testes de unidade.

Eu não consideraria componentes filhos com mapStateToPropsno React stateless porque eles ainda precisam saber como ler da loja e escrever testes de unidade para isso também será difícil porque você teria que simular a loja ou dar a loja ao fazer a unidade testes.

Outra vantagem desse detalhamento é que um componente é responsável pela leitura da loja e, se a estrutura da loja mudar, a mudança de código deve ser feita em um componente e as propriedades fluirão como antes. Mas com a aproximação de cada componente filho tendo mapStateToProps, a mudança da estrutura da loja teria sido feita em cada local que tivesse mapStateToProps.

Se você quiser ter this.store.select()em vários lugares, tudo bem, mas isso é equivalente a mapStateToPropsem vários lugares. Basicamente, se você puder fazer o detalhamento do suporte conforme descrito, o teste de unidade e a refatoração serão mais fáceis.