0

I'm using a mock json file called recipe.json. My intentions are to load the data when user enters the page. But whenever I hot reload the page nothing loads. If I want to load the data I have to save the file which then loads all the json data.

Here's the function that fetches the data:

  List<RecipeModel> recipes = [];
  Future<List<RecipeModel>> getRecipeData() async {
    // var response = await http.get(
    //   Uri.https("jsonplaceholder.typicode.com", 'users'),
    // );
    String response = await DefaultAssetBundle.of(context)
        .loadString('assets/json/recipe.json');
    var result = json.decode(response);

    for (var u in result["data"]) {
      RecipeModel recipe = RecipeModel(
        id: u['id'] ?? "",
        name: u['name'] ?? "",
        videoLink: u['videoLink'] ?? "",
        author: u['author'] ?? "",
        category: u['category'] ?? "",
        time: u['time'] ?? "",
      );
      recipes.add(recipe);
    }

    print(recipes.length);

    return recipes;
  }

  @override
  void initState() {
    super.initState();
    getRecipeData();
  }

Here's the ListView:

      Container(
        height: 250.0,
        child: ListView.builder(
          scrollDirection: Axis.horizontal,
          itemCount: recipes.length,
          itemBuilder: (BuildContext context, int index) {
            return RecipeCard(
                itemName: recipes[index].name,
                categoryName: recipes[index].category,
                time: recipes[index].time);
          },
        ),
      ),

My RecipeCard is a stateless widget which has itemname, categoryName and time marked as required.

Here's a fraction of the code from RecipeCard.dart:

class RecipeCard extends StatelessWidget {
  final String itemName;
  final String categoryName;
  final String time;
  RecipeCard(
      {required this.itemName, required this.categoryName, required this.time});
  @override
  Widget build(BuildContext context) {}
}
1
  • 2
    You are using a stateless widget, but loading data from an api is an async function. The data is loaded after the UI is built. So you need to rebuild the UI after loading data. To solve the issue, you need to whether use a statefull widget or FutureBuilder as @John Joe's answer. Commented Apr 28, 2021 at 9:35

1 Answer 1

1

Use FutureBuilder to get the json data

 FutureBuilder(
                future: getRecipeData(),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return ListView.builder(
                      scrollDirection: Axis.horizontal,
                      itemCount: recipes.length,
                      itemBuilder: (BuildContext context, int index) {
                        return RecipeCard(
                            itemName: recipes[index].name,
                            categoryName: recipes[index].category,
                            time: recipes[index].time);
                      },
                    );
                  } else {
                    return Text("~");
                  }
                }),
Sign up to request clarification or add additional context in comments.

3 Comments

So, basically call the function inside the future builder and not the initState? How can I do the same without using FutureBuilder and by converting the stateless widget to stateful like @ehsan suggested?
yes, you don't need to call it in initState. Why don't use FutureBuilder ?
well I was thinking to fetch all the data as soon as the page loads would be good idea, so that I wont have to call the function again and again inside different components

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.