A month of Flutter: extract post item widget
Yesterday I created the PostList
widget to display multiple posts at once. It contained the code for rendering both the list and the individual items. As the rendering logic for the individual items is going to get more complex, I'm going to extract the item rendering code into a PostItem
widget.
There aren't any feature changes in this refactor, but the PostItem
lays the groundwork for adding the code to render the image, name, date, etc. That complexity should be contained within this new widget.
class PostItem extends StatelessWidget {
const PostItem();
@override
Widget build(BuildContext context) {
return Card(
child: Container(
height: 300.0,
child: const Center(
child: Text('Prim Birb'),
),
),
);
}
}
One of the issues I see in some flutter tutorials is having widgets that are overly complex. Widgets that contain to much functionality are hard to read and test, and should be broken up into smaller widgets.
The code for PostsList
is now much more concise:
class PostsList extends StatelessWidget {
const PostsList();
static const List<int> _items = <int>[0, 1, 2];
@override
Widget build(BuildContext context) {
return ListView(children: _itemList());
}
List<PostItem> _itemList() {
return _items.map((int index) => const PostItem()).toList();
}
}
Separating the code into multiple widgets makes unit testing easier. Tests for how a PostItem
renders content can be contained within post_item_test.dart
and posts_list_test.dart
only has to test that PostItems
are rendered.
Tests for PostItem
:
testWidgets('Renders a post', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MaterialApp(
home: PostItem(),
));
expect(find.byType(Card), findsOneWidget);
expect(find.text('Prim Birb'), findsOneWidget);
});
Tests for PostsList
:
testWidgets('Renders list of posts', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MaterialApp(
home: PostsList(),
));
expect(find.byType(PostItem), findsNWidgets(2));
});