1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Flutter] Getting "Bad state: No element" error when I try to see the elections list in flutter

Discussão em 'Mobile' iniciado por Stack, Outubro 7, 2024 às 02:42.

  1. Stack

    Stack Membro Participativo

    I'm building a decentralized voting app using Flutter and this is my code to fetch the list of all elections (Ongoing and previous)

    import 'dart:io';

    import 'package:flutter/material.dart';
    import 'package:voting_app/services/functions.dart';
    import 'package:voting_app/utils/constants.dart';
    import 'package:web3dart/web3dart.dart';
    // Assume you have web3dart package and proper Ethereum connection initialized
    // import 'package:web3dart/web3dart.dart';

    class Electionslist extends StatefulWidget {
    final Web3Client ethClient;
    const Electionslist({super.key, required this.ethClient});

    @override
    State<Electionslist> createState() => _ElectionslistState();
    }

    class _ElectionslistState extends State<Electionslist> {
    List<Map<String, dynamic>> elections = [];

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

    Future<void> fetchElections() async {
    try {
    // Fetch elections from the blockchain
    List<dynamic> fetchedElections = await getElections(widget.ethClient);

    // Log the raw data to understand its structure
    print('Fetched Elections: $fetchedElections');
    print('Fetched Elections length: ${fetchedElections.length}');

    // Ensure the fetched data contains two arrays: one for names and one for statuses
    if (fetchedElections.length < 2) {
    print('Invalid data returned from the contract');
    return;
    }

    // Log each array type and content
    print('Election names data: ${fetchedElections[0]}');
    print('Election statuses data: ${fetchedElections[1]}');
    print('Election names data type: ${fetchedElections[0].runtimeType}');
    print('Election statuses data type: ${fetchedElections[1].runtimeType}');

    // Try casting to expected types
    List<String> names = List<String>.from(fetchedElections[0]);
    List<bool> statuses = List<bool>.from(fetchedElections[1]);

    // Log the processed lists
    print('Election Names: $names');
    print('Election Statuses: $statuses');

    // Convert the lists to a Map and update the state
    setState(() {
    elections = List<Map<String, dynamic>>.generate(names.length, (index) {
    return {
    'name': names[index],
    'isOngoing': statuses[index],
    };
    });
    });
    print('Elections updated successfully');
    } catch (e) {
    print('Error: $e');
    print(await widget.ethClient
    .getBalance(EthereumAddress.fromHex(owner_address)));
    }
    }

    // Divide elections into ongoing and previous
    List<Map<String, dynamic>> get ongoingElections =>
    elections.where((e) => e['isOngoing']).toList();

    List<Map<String, dynamic>> get previousElections =>
    elections.where((e) => !e['isOngoing']).toList();

    Future<void> _stopElection(int electionIndex) async {
    List<dynamic> fetchedElections = await getElections(widget.ethClient);

    if (electionIndex < 0 || electionIndex >= fetchedElections.length) {
    throw Exception("Invalid election index: $electionIndex");
    }

    print(electionIndex);
    await stopElection(widget.ethClient, electionIndex);
    fetchElections();
    }

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    appBar: AppBar(
    title: Text('Elections List'),
    ),
    body: Padding(
    padding: const EdgeInsets.all(8.0),
    child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    Text(
    'Ongoing Elections',
    style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
    ),
    Expanded(
    child: ListView.builder(
    itemCount: ongoingElections.length,
    itemBuilder: (context, index) {
    return Card(
    child: ListTile(
    title: Text(ongoingElections[index]['name']),
    trailing: ElevatedButton(
    onPressed: () {
    _stopElection(index);
    },
    child: Text('Stop')),
    ),
    );
    },
    ),
    ),
    SizedBox(height: 16),
    Text(
    'Previous Elections',
    style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
    ),
    Expanded(
    child: ListView.builder(
    itemCount: previousElections.length,
    itemBuilder: (context, index) {
    return Card(
    child: ListTile(
    title: Text(previousElections[index]['name']),
    ),
    );
    },
    ),
    ),
    ],
    ),
    ),
    );
    }
    }



    when I run this, I get the Bad state: No element error. This is my solidity code for getElections:

    function getElections()
    public
    view
    returns (string[] memory, bool[] memory)
    {
    string[] memory names = new string[](elections.length);
    bool[] memory statuses = new bool[](elections.length);

    for (uint i = 0; i < elections.length; i++) {
    names = elections.name;
    statuses = elections.isOngoing;
    }

    return (names, statuses);
    }



    I am using hardhat node for testing, and the contract address is also correct.

    This is the UI for elections list elections list

    I initially did not have the elections list feature, so when I added the elections list code, I even changed the ABI file in flutter to the new one. Also tried redeploying the smart contract but that did not work. My hardhat node is correctly connected with the frontend as I can see the transactions calls to the smart contract very clearly in hardhat terminal. When I run the above dart code I only see the call to get eth balance as it directly goes to the catch block when I try to see the elections list. It is not the case that the list is empty either since I make sure to add the elections before seeing the list.

    Continue reading...

Compartilhe esta Página