0

I am trying to modify the List fetched during the future call and not call the future function again, so assigned a variable to future option of FutureBuilder and called the actual function in the initState(), but now the build function is rendering straight the snapshot.error condition and the build is not even going in the ConnectionState.loading state. Below is the relevant code snippet:

class _BusinessDetailScreenState extends State<BusinessDetailScreen> {
  late List<ProductCategory> _uniqueProductCategoryList;
  late Future<List<BusinessProduct>> _productsFetch;

  @override
  void initState() {
    super.initState();
    _productsFetch = _fetchDetails();
  }

  List<ProductCategory> fetchUniqueCategory (productList) {
    // function body
    return List<ProductCategory>.generate(result.length, (index) {
        return ProductCategory(
          categoryName: result[index]["productCategoryName"],alternateName: result[index]["productCategoryAlternateName"]??= "", id:result[index]["id"]
        );
    });
  }

  Future<List<BusinessProduct>> _fetchDetails() async {
    var queryParams = {
     //params
    };
    var response = await http.get(Uri.https(Provider.of(context)!.baseUrl,'endpoint',queryParams));
    if (response.statusCode == 200) {
      List jsonResponse = json.decode(response.body);
      List<BusinessProduct> products = jsonResponse.map((e) => BusinessProduct.fromJson(e)).toList();
      _uniqueProductCategoryList = fetchUniqueCategory(products);
      return products;
    }else {
      throw Exception('Failed to load Details');
    }
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<dynamic>>(
      future: _productsFetch,
      builder: (context,snapshot){
      print(snapshot); //AsyncSnapshot<List<dynamic>>(ConnectionState.done, null, dependOnInheritedWidgetOfExactType<Provider>() or dependOnInheritedElement() was called before _BusinessDetailScreenState.initState() completed.
        if(snapshot.hasData){
          return Scaffold(//for data)
        } else if(snapshot.hasError){
            print(snapshot.error);
            // I/flutter ( 4211): dependOnInheritedWidgetOfExactType<Provider>() or dependOnInheritedElement() was called before _BusinessDetailScreenState.initState() completed.

            return Scaffold( // for error)
        } return Scaffold(
            backgroundColor: palletWhite,            
            body: Center(
              child: LoadingComponent(loadingText: 'Fetching data, Please wait',)
            )
        );
      },
    );
  )

Been stuck on this for a while now, is there anything I'm doing wrong or is there some different approach to this that I should try, please let me know

Amit Dubey
  • 75
  • 1
  • 8
  • what is in `snapshot.error`? – pskink Jun 13 '21 at 10:23
  • ````snapshot.data``` is getting value ```null```, that's why it is just going to ```snapshot.hasError``` – Amit Dubey Jun 13 '21 at 10:25
  • i asked about `snapshot.error`, not `snapshot.data` - simply add `print(snapshot);` before `if(snapshot.hasData){`, what do you see on the logs? – pskink Jun 13 '21 at 10:26
  • yeah, sorry my bad, edited the question with content of snapshot.error, getting this: ```I/flutter ( 4211): dependOnInheritedWidgetOfExactType() or dependOnInheritedElement() was called before _BusinessDetailScreenState.initState() completed.``` – Amit Dubey Jun 13 '21 at 10:28
  • ```E/flutter ( 3677): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: dependOnInheritedWidgetOfExactType() or dependOnInheritedElement() was called before _BusinessDetailScreenState.initState() completed. E/flutter ( 3677): When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget.``` – Amit Dubey Jun 13 '21 at 10:51
  • ```E/flutter ( 3677): Typically references to inherited widgets should occur in widget build() methods. Alternatively, initialization based on inherited widgets can be placed in the didChangeDependencies method, which is called after initState and whenever the dependencies change thereafter.``` - Stacktrace after commenting FutureBuilder @pskink – Amit Dubey Jun 13 '21 at 10:52
  • Hey, so got the answer, the issue was in ```Provider.of(context)!.baseUrl``` used to fetch baseUrl, as per the answer of [link](https://stackoverflow.com/questions/60363665/dependoninheritedelement-was-called-before-initstate-in-flutter) - *Provider.of(context) is supposed to be used inside the widget tree, and anything that is outside of the build() method, is not in the widget tree.* , so replaced that – Amit Dubey Jun 13 '21 at 11:06

1 Answers1

0

With reference to the answer on link - Provider.of(context) is supposed to be used inside the widget tree, and anything that is outside of the build() method, is not in the widget tree. But if you still want to use it, then you need to set the listen parameter to false So replacing Provider.of(context)!.baseUrl in _fetchDetails(), helped resolving the issue. Thanks to @musausman.com and @pskink

Amit Dubey
  • 75
  • 1
  • 8