[英]Flutter_bloc: ^8.0.0 State does not rebuild when emitting the same state with different props
我正在試驗 state 管理原型,最近偶然發現了一個問題。 問題是一個交互確實會重新加載屏幕,這很好。 雖然另一個交互不會重新加載屏幕,即使它發出相同的 state(也具有更改的道具)。
我的原型有 3 個屏幕:
屏幕截圖中的星星在下面的小部件中表示:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:state_management/models/product/product.dart';
import 'package:state_management/models/product/product_bloc.dart';
class RatingBox extends StatefulWidget {
final Product item;
RatingBox({
Key ? key, required this.item
}): super(key: key);@
override
_RatingBoxState createState() {
return _RatingBoxState();
}
}
class _RatingBoxState extends State < RatingBox > {@
override
Widget build(BuildContext context) {
double _size = 20;
return Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: [
for (int i = 1; i <= 3; i++)
Container(
padding: const EdgeInsets.all(0),
child: IconButton(
icon: (widget.item.rating >= i ? Icon(
Icons.star,
size: _size,
) : Icon(
Icons.star_border,
size: _size,
)),
color: Colors.red[500],
onPressed: () {
context.read < ProductBloc > ().add(UpdateProductRating(
product: widget.item.copyWith(rating: i)));
},
iconSize: _size,
),
),
],
);
}
}
表單通過提交按鈕更新,使用另一個事件(出於測試目的)。 但它里面有相同的代碼:
context.read < ProductBloc > ().add(UpdateProduct(
product: item.copyWith(
name: item.name,
description: item.description,
price: item.price)));
下面的代碼是product_bloc、product_event和product_state的代碼:
class ProductBloc extends Bloc < ProductEvent, ProductState > {
ProductBloc(): super(ProductLoading()) {
on < LoadProduct > (_onLoadProduct);
on < UpdateProduct > (_onUpdateProduct);
on < UpdateProductRating > (_onUpdateProductRating);
}
void _onLoadProduct(LoadProduct event, Emitter < ProductState > emit) {
print('load');
emit(
ProductLoaded(products: event.products),
);
}
void _onUpdateProductRating(
UpdateProductRating event, Emitter < ProductState > emit) {
final state = this.state;
if (state is ProductLoaded) {
print('updateRating');
List < Product > products = (state.products.map((product) {
return product.id == event.product.id ? event.product : product;
})).toList();
emit(ProductLoaded(products: List.of(products)));
}
}
void _onUpdateProduct(UpdateProduct event, Emitter < ProductState > emit) {
final state = this.state;
if (state is ProductLoaded) {
print('update');
List < Product > products = (state.products.map((product) {
return product.id == event.product.id ? event.product : product;
})).toList();
emit(ProductLoaded(products: products));
}
}
}
abstract class ProductEvent extends Equatable {
const ProductEvent();@
override
List < Object > get props = > [];
}
class LoadProduct extends ProductEvent {
final List < Product > products;
const LoadProduct({
this.products = const < Product > []
});@
override
List < Object > get props = > [products];
}
class UpdateProduct extends ProductEvent {
final Product product;
const UpdateProduct({
required this.product
});@
override
List < Object > get props = > [product];
}
class UpdateProductRating extends ProductEvent {
final Product product;
const UpdateProductRating({
required this.product
});@
override
List < Object > get props = > [product];
}
abstract class ProductState extends Equatable {
const ProductState();@
override
List < Object > get props = > [];
}
class ProductLoading extends ProductState {}
class ProductLoaded extends ProductState {
final List < Product > products;
const ProductLoaded({
this.products = const < Product > []
});@
override
List < Object > get props = > [products];
}
最重要的部分是在更改下一頁上的表單時設置星星並不能解決問題。 奇怪的是它會改變,如果我在發出 state 之前發出另一個 state 我希望應用程序進入。
我希望這對大家有意義。 這是我在 StackOverflow 上的第一篇文章,因此我將不勝感激!
我找到了問題!
我過早地設置了我的項目屬性,這導致 BLoC 無法識別更改,因為它是正在設置的同一產品。
因此,不要在 onChange 事件中設置 item.xx,而是嘗試將結果存儲在另一個地方,例如 TextEditingController。 然后在提交表單時,使用存儲的數據創建一個新的 object,這將被識別為更改。
如果您使用 Equatable,請確保將所有屬性傳遞給 props getter。
abstract class MyState extends Equatable {
const MyState();
}
class StateA extends MyState {
final String property;
const StateA(this.property);
@override
List<Object> get props => [property]; // pass all properties to props
}
它對我有用,希望對你也有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.