Hi, Im pretty new to bloc+Cubit library so I got at the question of how to keep data between different state.
Image you have three states
and the user does the following:
1.when app fetch a list of products successfully, then we send back FetchProductSuccess( products) to render on ui.
What if the refresh fails and I still want to display the old list of products? I'm quite confused about where to keep this temp data in cubit+bloc pattern. Any suggestions?
Hi @PandaGeek1024 馃憢
Thanks for opening an issue!
In cases where you want to retain the old data while processing a new request, I would recommend refactoring the way you are modeling the state:
enum ProductStatus { initial, loading, success, failure }
class ProductState {
const ProductState({
this.status = ProductStatus.initial,
this.products = const <Product>[],
});
final ProductStatus status;
final List<Product> products;
ProductState copyWith({ProductStatus status, List<Product> products}) {
return ProductState(
status: status ?? this.status,
products: products ?? this.products,
);
}
}
Then in your bloc/cubit you can use state.copyWith to emit new states and you will still have access to the old products list even if you are fetching a new list and the status is loading.
For a concrete example of this you can check out fluttersaurus.
Closing for now but feel free to comment with additional questions and I'm happy to continue the conversation 馃憤
For a concrete example of this you can check out fluttersaurus.
But there is no state.copyWith example on the above link.
Hi @omidraha 馃憢
The copyWith method is omitted, but you can easily add it.
Named constructors are used instead of an enum status to identify different states, so in that case yielding new states is done by using the constructors instead of the copyWith pattern. It's up to your setup and preference.
It also matters whether you want to persist existing properties throughout different states. If if you need to drag the list of synonyms though multiple loading states then you might wanna use a copyWith approach.
Hope that helps 馃憤
When we are using copyWith approach, Is it possible to set again a variable to null?
For example because we have something like this in copyWith method:
order: order ?? this.order,
If order already has some value, we can't set order tonull, with this:
state.copyWith(order:null);
@omidraha you can create a custom copyWith that accepts methods instead to enable returning null values:
void main() {
final bob = Person(name: 'Bob', age: 42);
final nullName = bob.copyWith(name: () => null);
print(bob); // Person(Bob, 42)
print(nullName); // Person(null, 42)
}
class Person {
const Person({this.name, this.age});
final String name;
final int age;
Person copyWith({
String Function() name,
int Function() age,
}) {
return Person(
name: name != null ? name() : this.name,
age: age != null ? age() : this.age,
);
}
@override
String toString() => 'Person($name, $age)';
}
Hope that helps 馃憤
Hi guys!
I currently have a similar issue on my project, and I'm sure that this will solve it! The only "problem" is that I'm currently using freezed to generate my states and event classes.
Not trying to sound lazy here, but @felangel can you please show me how that state class would be written using freezed? Or is it only achievable by using enums?
Thanks for your hard work on this package! 馃槃
Most helpful comment
@omidraha you can create a custom
copyWiththat accepts methods instead to enable returning null values:Hope that helps 馃憤