App/Flutter
A RenderShrinkWrappingViewport expected a child of type RenderSliver but received a child of type RenderConstrainedBox.
Agrafenaaa
2023. 2. 14. 16:31
ISSUE : CustomScrollView widget which consists of SlivderList(SliverChildBuilderDelegate) and is supported by riverpod state management suddenly occured the error below. Sliver-related widget doesn't show the specified widget from provider's when method (error: (err, stackTrace) => const SizedBox()) and throws an exception
Error Output
Code:
list() {
final notifications = ref.watch(notificationProvider);
return Expanded(
child: NotificationListener<ScrollEndNotification>(
child: Scrollbar(
thickness: 0,
child: RefreshIndicator(
onRefresh: () async {
ref.read(notificationProvider.notifier).getList();
},
child: CustomScrollView(
shrinkWrap: true,
restorationId: 'notifications',
slivers: <Widget>[
notifications.when(data: (data) {
context.loaderOverlay.hide();
return SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, idx) => _push(notification: data[idx]),
childCount: data.length,
),
);
}, loading: () {
context.loaderOverlay.show(widget: const Spinner());
return const SizedBox();
}, error: (err, stackTrace) {
if (notifications.hasValue) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, idx) =>
_push(notification: notifications.value![idx]),
childCount: notifications.value!.length,
),
);
}
return const SizedBox();
}),
LazyLoadingBottom(asyncValue: notifications),
],
),
),
),
),
);
}
Solution 1 -> Add an additional condition if the data is empty. (Failed)
notifications.when(data: (data) {
context.loaderOverlay.hide();
if (data.isNotEmpty) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, idx) => _push(notification: data[idx]),
childCount: data.length,
),
);
} else {
return const SizedBox();
}
Solution 2 -> Check if the data object field name has changed. (applicable partly)
ex) NotificationModel => topicType json key has changed from "msg_notice" to "msgNotice".
Solution 3 -> Reorder widget tree. NotificationListener should be inside "data" instead of putting list provider when method INSIDE "NotificationListener" to avoid errors.
Expanded(
child: notifications.when(
data: (data) {
if (data.isNotEmpty) {
return NotificationListener<ScrollEndNotification>(
child: Scrollbar(
thickness: 0,
child: RefreshIndicator(
onRefresh: () async {
ref
.refresh(notificationProvider.notifier)
.getList();
},
child: CustomScrollView(
shrinkWrap: true,
restorationId: 'notifications',
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, idx) => _push(notification: data[idx]),
childCount: data.length,
),
),
LazyLoadingBottom(asyncValue: notifications),
],
),
),
),
);
} else {
return const SizedBox();
}
},
loading: () => const Spinner(),
error: (error, stackTrace) => const SizedBox(),
),
),