flutter_architecture_samples
flutter_architecture_samples copied to clipboard
What would cause a Flutter Redux StoreConnector to not rebuild.
I try to follow the issues religiously on the flutter_architecture_sample. Thank you, to all of you that contribute and ask questions. It helps a lot. I have not seen an issue like this and I could not find the right search query to bring up anything close to my problem. I would really appreciate some help if anyone has an idea as to why this StoreBuilder is not rebuilding. The underlying state of the reducer is two Map<String, Whatevers>'s. I tried to add code without overwhelming the post.
#View
return ListView.builder(
itemCount: eventIDs.length,
itemBuilder: (BuildContext context, int i) {
return StoreConnector<AppState, EventsPageViewModel>(
rebuildOnChange: true,
onDidChange: (EventsPageViewModel events) {print('${events}');},
onInit: (store) =>
store.dispatch(FetchEventAction(id: eventIDs[i])),
converter: (store) => EventsPageViewModel.fromStore(store),
builder: (BuildContext context, EventsPageViewModel events) {
print("build ListItem $i ${eventIDs[i]}");
if (events.events.containsKey('${eventIDs[i]}')) {
return EventCard(
event: events.events[eventIDs[i]],
);
}
return Container(
child: Card(
child: Container(
height: 120.0,
),
),
);
});
},
);
#State
@immutable
class Events {
Events({
this.loadingStatus,
this.events,
});
factory Events.initial() {
return Events(
loadingStatus: Map<String, LoadingStatus>(),
events: Map<String, EventModel>(),
);
}
final Map<String, LoadingStatus> loadingStatus;
final Map<String, EventModel> events;
Events copyWith({
Map<String, LoadingStatus> loadingStatus,
Map<String, EventModel> events,
}) {
return Events(
loadingStatus: loadingStatus ?? this.loadingStatus,
events: events ?? this.events,
);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Events &&
runtimeType == other.runtimeType &&
loadingStatus == other.loadingStatus &&
const MapEquality().equals(events, other.events);
@override
int get hashCode => loadingStatus.hashCode ^ const MapEquality().hash(events);
}
#ViewModel
class EventsPageViewModel {
EventsPageViewModel({
@required this.status,
@required this.events,
});
final Map<String, LoadingStatus> status;
final Map<String, EventModel> events;
static EventsPageViewModel fromStore(
Store<AppState> store,
) {
return EventsPageViewModel(
status: store.state.events.loadingStatus,
events: store.state.events.events,
);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is EventsPageViewModel &&
runtimeType == other.runtimeType &&
status == other.status &&
const MapEquality().equals(events, other.events);
@override
int get hashCode => status.hashCode ^ const MapEquality().hash(events);
}
I'm trying to get a view to rebuild after it fire off an async action and it return a value to a Map. I don't know if i'm doing the equality check properly
I checked to see if the middleware was firing off the GET Request. It is. I checked to see if the GET request was returning information. It is. I have another async action that is firing. That one returns a List of string and does trigger a rebuild on its StoreConnector.
Does anyone have any clues as to why the StoreConnector does not detect a diff?
Hey there -- hrm, this is a funny one. I can't quite spot anything suspicious in the code that you've pasted, it looks pretty "standard" to me. Do you happen to have a full project you can share, or perhaps sharing some of the Middleware / Reducer code as well?
https://github.com/Joematpal/trial-flutter-app
Thank you for looking at this.
@Joematpal The link above is no longer working. Were you able to resolve this? If so please close this issue. Otherwise feel free to add to this issue.
@Joematpal I have the same issue as yours, Were you able to resolve the problem?
I could be wrong, but I believe this is because Maps (as well as Lists) need to return a new Map (or List) on update from the reducer. You cannot update the old map because the Redux package will not understand that it needs to rebuild. I assume this is due to the internals of the built in Map and List objects being unable to accurately create a hashCode/equals due to the generics, but I'm not 100% sure.