Simple web fetch fails

Viewed 35

I'm trying to write my first code to fetch data from a web API and display it on my web page. I follow a tutorial but for some reason my code doesn't work and instead VSCode's debug console keeps spitting out all kinds of errors when I run the app.

I presume the problem is somewhere in the state management code but can't pinpoint where exactly.

I build it as a website and run in Chrome.

What am I doing wrong?

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import '../dtos/dto_objects.dart';
import '../settings/schemes/color_scheme.dart';
import '../components/navbar.dart';

class ContentPage extends StatefulWidget {
  const ContentPage({super.key});

  @override
  State<ContentPage> createState() => _ContentPageState();
}

class _ContentPageState extends State<ContentPage> {
  var _posts = [];

  void fetchPosts() async {
    try
    {
      String url = "https://jsonplaceholder.typicode.com/posts";
      final response = await get(Uri.parse(url));
      final jsonData = jsonDecode(response.body) as List;

      setState(() {
        _posts = jsonData;
      });
    } catch (err) {}
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    fetchPosts();
  }


  @override
  Widget build(BuildContext context) {
    // First prepare dummy items in case fetching from web fails
    Post dummyCrs1 = new Post(id: "ccc1", userId: "1", title: "Fetching data...", body: "Fetching description...");
    Post dummyCrs2 = new Post(id: "ccc2", userId: "1", title: "Fetching data...", body: "Fetching description...");
    _posts.add(dummyCrs1);
    _posts.add(dummyCrs2);

    return Scaffold(
      backgroundColor: schemeBackgroundColor,

      body: ListView(
        children: [
          Center(child: NavBar()),

          Center(
            child:
                ListView.builder(
                  itemCount: _posts.length,
                  itemBuilder: (context, i) {
                    final post = _posts[i];
                    return Text("Title: ${post["title"]}, Body: ${post["body"]}\n");
                  }
                )
          )
        ]
      )
    );
  }
}

A screenshot of what my debug console looks like when I open the page with this widget: enter image description here

2 Answers

Adding ListView.builder inside ListView is not required. You can refer below code. API call logic is working as expected.

Scaffold(
        backgroundColor: Colors.white,
        body: Container(
          child: ListView.builder(
              itemCount: _posts.length,
              itemBuilder: (context, i) {
                final post = _posts[i];
                return Text("Title: ${post["title"]}, Body: ${post["body"]}\n");
              }),
        ));

Use this simple way

import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart';

void main() {
  runApp(const ContentPage());
}

class ContentPage extends StatefulWidget {
  const ContentPage({super.key});

  @override
  State<ContentPage> createState() => _ContentPageState();
}

class _ContentPageState extends State<ContentPage> {
  Future fetchPosts() async {
    String url = "https://jsonplaceholder.typicode.com/posts";
    final response = await get(Uri.parse(url));
    final body = jsonDecode(utf8.decode(response.bodyBytes));
    return body;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder(
          builder: (ctx, snapshot) {
            if (snapshot.hasData) {
              var body;
              body = snapshot.data;
              return ListView.builder(
                  itemCount: body.length,
                  itemBuilder: (context, i) {
                    final post = body[i];
                    return Text(
                        "Title: ${post["title"]}, Body: ${post["body"]}\n");
                  });
            }
            // Displaying LoadingSpinner to indicate waiting state
            return Center(
              child: CircularProgressIndicator(),
            );
          },
          // Future that needs to be resolved
          // inorder to display something on the Canvas
          future: fetchPosts(),
        ),
      ),
    );
  }
}

enter image description here

Related