Describe the bug
In a chat application, I am using a global variable to update the badge of the pending notifications in the main bar, and also in a report view, that is in fact a component. In the main bar, it keeps in sync, but inside the component, even after using ConnOp and connected successfully with the host page, the only way to have it updated is calling the global store twice. Believe me, I tested with Future.delayed(Duration...)), also added await in all correct places, but the only solution is calling the dispatch twice.
I am Show the code you wrote as completely as possible.
Effect<VisitState> buildEffect() {
return combineEffects(<Object, Effect<VisitState>>{
VisitAction.action: _onAction,
VisitAction.refresh: _onRefresh,
Lifecycle.initState: _onInit,
Lifecycle.dispose: _onDispose
});
}
void _onAction(Action action, Context<VisitState> ctx) {}
/// When HTTP is done, we use a [FutureBuilder] to render the UI
/// to help reading we will use a short name [con]
void _onInit(Action action, Context<VisitState> ctx) async {
ctx.state.scrollController = ScrollController();
// see https://stackoverflow.com/questions/49807687/how-to-load-all-dart-dateformat-locale-in-flutter
await initializeDateFormatting();
// pooling
//Timer.periodic(Duration(seconds: 20), (_) => _loadAppointments(action, ctx));
await _onRefresh(action, ctx);
//ctx.state.appointments = fakeAppointments();
}
/// Clean resources
void _onDispose(Action action, Context<VisitState> ctx) =>
ctx.state.scrollController?.dispose();
/// Retrieve [Appointment] list for this user using the JWT as an user
/// identification, so we don't need to send the appUser.id
/// final appUser = GlobalStore.store.getState().user;
void _onRefresh(Action action, Context<VisitState> ctx) async {
ctx.dispatch(VisitActionCreator.loading(true));
var notifCount = await _getPending();
//GlobalStore.store.dispatch(GlobalActionCreator.setNotificationCount(notifCount));
//ctx.state.notificationCount = notifCount;
await Client.rest.getAppointments().then((res) async {
ctx.state.appointments = res;
await _setSummary(res, ctx, notifCount);
}).catchError((Object obj) {
NetError er = RequestException.handleException(obj);
ToastMessage.show(er.msg);
});
ctx.dispatch(VisitActionCreator.loading(false));
// TODO: BUG HERE, leave it here twice... ugly, but works
GlobalStore.store.dispatch(GlobalActionCreator.setNotificationCount(notifCount));
GlobalStore.store.dispatch(GlobalActionCreator.setNotificationCount(notifCount));
// var notifCount2 = await _getPending();
}
/// set summary if we have [Appointment]
Future<void> _setSummary(List<Appointment> appointments, Context<VisitState> ctx, int notifCount) async {
if (appointments.length == 0) return;
String doctor = 'Dr. ' + appointments[0].healthcareProfessional.firstName + ' ' +
appointments[0].healthcareProfessional.lastName;
DateTime date = appointments[0].date.add(Duration(days: 1)); // add 1 day [to be correct]
Duration difference = date.difference(DateTime.now()); // calculates the diff
// setup summary
Summary summary = Summary(
doctor: doctor,
notificationCount: notifCount,
remainingDays: difference.inDays.toString()
);
ctx.dispatch(SummaryActionCreator.onSetSummary(summary));
print('sdfsdf'+notifCount.toString());
}
/// get pending converstations. It's ugly to call it again, maybe we could have it
/// in a global variable, or redesign the API
Future<int> _getPending() async {
int pending;
await Client.rest.getOnboarding().then((res) {
pending = res.pendingConversations;
}).catchError((Object obj) {
NetError er = RequestException.handleException(obj);
ToastMessage.show(er.msg);
});
return pending ?? 0;
}
class SummaryComponent extends Component<SummaryState> {
SummaryComponent()
: super(
effect: buildEffect(),
reducer: buildReducer(),
shouldUpdate: (oldItem, newItem) {
return newItem.notificationCount != oldItem.notificationCount ||
newItem.user != oldItem.user ||
newItem.locale != oldItem.locale;
},
view: buildView,
dependencies: Dependencies<SummaryState>(
adapter: null,
slots: <String, Dependent<SummaryState>>{
})
);
}
class SummaryState implements Cloneable<SummaryState> {
// days for the next appointment
String remainingDays;
String doctor;
Locale locale;
User user;
SummaryState clone() {
return SummaryState()
..remainingDays = remainingDays
..locale = locale
..notificationCount = notificationCount
..doctor = doctor;
}
int notificationCount;
}
class SummaryConnector extends ConnOp<VisitState, SummaryState> {
@override
SummaryState get(VisitState state) {
SummaryState subState = state.summaryState.clone();
subState.notificationCount = state.notificationCount;
subState.locale = state.locale;
// Log.debug('=======================---------->>>>>>>>>>>>>>>');
// Log.debug(state.locale.toString());
Log.debug(state.notificationCount.toString());
return subState;
}
@override
void set(VisitState state, SummaryState subState) {
// subState.notificationCount = state.notificationCount;
// subState.locale = state.locale;
state.summaryState = subState;
}
}
To Reproduce
have to land in the main view and see that the notificationCount conversation in summary view is null
Expected behavior
notificationCount should appear
Additional context
The version of fish-redux which you are using.
^0.3.4
The information from flutter doctor.
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.4, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[!] Android Studio (not installed)
[✓] VS Code (version 1.50.0)
[✓] Connected device (1 available)
Describe the bug In a chat application, I am using a global variable to update the badge of the pending notifications in the main bar, and also in a report view, that is in fact a component. In the main bar, it keeps in sync, but inside the component, even after using ConnOp and connected successfully with the host page, the only way to have it updated is calling the global store twice. Believe me, I tested with Future.delayed(Duration...)), also added await in all correct places, but the only solution is calling the dispatch twice. I am Show the code you wrote as completely as possible.
To Reproduce have to land in the main view and see that the notificationCount conversation in summary view is null Expected behavior notificationCount should appear
Additional context
The version of fish-redux which you are using. ^0.3.4
The information from flutter doctor.
Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 1.22.4, on Linux, locale en_US.UTF-8) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) [!] Android Studio (not installed) [✓] VS Code (version 1.50.0) [✓] Connected device (1 available)