skip to Main Content

I have a simple statefullWidget like this:

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late String _email;

  void getEmail() async {
    -> doing stuff and **set the value of _email**
  }

  @override
  void initState() {
    super.initState();
    getEmail(); //I invoke the method during the initstate()
  }

  @override
  Widget build(BuildContext context) {
    
    return Scaffold(
      body: SafeArea(
        child: Text(_email);
      ),
    );
  }
}

Doing this I get an exception saying me that the value of email is null.
I thought that the method initState() was called before the build method, but maybe I am wrong.

Do you have and idea to how to solve my problem?

P.S. If I declare the variable _email like this:

String _email = '';

my UI starts with a blank space and then is filled with the correct value of the email. I don’t want that, though.

3

Answers


  1. In this modification, I introduced a separate method _initializeState that calls getEmail and then updates the state using setState only if the widget is still mounted. This ensures that the UI is updated only when the asynchronous operation is completed.

    class HomeScreen extends StatefulWidget {
      const HomeScreen({super.key});
    
      @override
      State<HomeScreen> createState() => _HomeScreenState();
    }
    
    class _HomeScreenState extends State<HomeScreen> {
      late String _email;
    
      Future<void> getEmail() async {
        // ... doing stuff and setting the value of _email
      }
    
      @override
      void initState() {
        super.initState();
        _initializeState();
      }
    
      Future<void> _initializeState() async {
        await getEmail();
        if (mounted) {
          // Ensure the widget is still part of the widget tree.
          setState(() {
            // This will trigger a rebuild and update the UI with the correct email.
          });
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Text(_email),
          ),
        );
      }
    }
    
    Login or Signup to reply.
  2. Use a FutureBuilder if the getMail method takes some time:

    return Scaffold(
        body: SafeArea(
          child: FutureBuilder(
            future: getEmail(), //Return type should be Future<String>
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return const Center(child: CircularProgressIndicator());
              } else if (snapshot.hasError) {
                return Text(snapshot.error.toString());
              } else if (snapshot.hasData) {
                return Text(snapshot.hasData.toString());
              } else {
                return const Text('No data available');
              }
            },
          ),
        ),
      );
    
    Login or Signup to reply.
  3. Your logic is correct, but you need to add value in a simple way.

    Try this:

    void getEmail() async {
            -> doing stuff and **set the value of _email**
            _email = '[email protected]';
          }
    

    .

      @override
      void initState() {
        getEmail(); //I invoke the method during the initstate()
        super.initState();      
    }
    

    if you want to get email from other Widget (other screen) you have to add Static member variables like this :

    class HomeScreen extends StatefulWidget {
      const HomeScreen({super.key,required this.emailFromOtherScreen});
    
    
     ////////////////////////////////////////
        final String emailFromOtherScreen;
    ////////////////////////////////////////
    
    
      @override
          State<HomeScreen> createState() => _HomeScreenState();
        }
    
    class _HomeScreenState extends State<HomeScreen> {
      late String _email;
    
      void getEmail() async {
        -> doing stuff and **set the value of _email**
       _email = widget.emailFromOtherScreen;
      }
    
      @override
      void initState() {
        super.initState();
        getEmail(); //I invoke the method during the initstate()
      }
    
      @override
      Widget build(BuildContext context) {
        
        return Scaffold(
          body: SafeArea(
            child: Text(_email);
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search