Search code examples
flutterriverpodtexteditingcontroller

Use TextEditingController in Riverpod ConsumerWidget


I have a ConsumerWidget, which I'm using to watch the state of a provider. Anyways everything is working, besides my TextEditingControllers. Whenever I type something into the text field and click the done button on the phone keyboard, the textfields goes empty again. I think this is due to the state of that widget. So my question is how do I use the TextEditingController inside the ConsumerWidget, which has no createState method?

Here is my code. Thanks in advance:


class MainPage extends ConsumerWidget {
  const MainPage({super.key});

  @override
  Widget build(BuildContext context, ref) {
    // provider
    final roomListData = ref.watch(roomDataProvider);

    final roomService = RoomService();

    final roomIDController = TextEditingController();
    final roomPasswordController = TextEditingController();

    // UI screen size
    final size = MediaQuery.of(context).size;

    double deviceWidth = size.width;
    double deviceHeight = size.height;

    return Scaffold(
        backgroundColor: bluePrimary,
        body: SingleChildScrollView(
          child: roomListData.when(
              data: (data) {
                List<RoomModelResponse> roomList =
                    data.map((room) => room).toList();
                return SafeArea(
                    child: Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 36, vertical: 16),
                  child: Column(
                      //crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            IconButton(
                              iconSize: deviceWidth * 0.09,
                              icon: const Icon(Icons.person_outline,
                                  color: orangePrimary),
                              onPressed: () {
                                Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) =>
                                            const DetailedProfilePage()));
                              },
                            ),
                            IconButton(
                              icon: const Icon(
                                Icons.add,
                                color: orangePrimary,
                              ),
                              iconSize: deviceWidth * 0.09,
                              onPressed: () {
                                Navigator.push(
                                  context,
                                  MaterialPageRoute(
                                      builder: (context) =>
                                          const CreateRoomScreen()),
                                );
                              },
                            )
                          ],
                        ),
                      
                        SizedBox(height: deviceHeight * 0.04),
                        Align(
                          alignment: Alignment.centerLeft,
                          child: Text("Join room",
                              style: TextStyle(
                                fontFamily: 'Chalet',
                                fontSize: deviceWidth * 0.05,
                                color: whitePrimary,
                                fontWeight: FontWeight.w100,
                              )),
                        ),
                        SizedBox(height: deviceHeight * 0.008),

                        // room ID textField
                        SizedBox(
                          width: MediaQuery.of(context).size.width * 0.85,
                          child: TextField(
                            controller: roomIDController,
                            decoration: InputDecoration(
                                filled: true,
                                fillColor: whitePrimary,
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(12),
                                    borderSide: BorderSide.none),
                                hintText: 'Enter room ID to join it',
                                hintStyle: const TextStyle(
                                    color: Color.fromARGB(255, 174, 173, 173))),
                          ),
                        ),

                        SizedBox(height: deviceHeight * 0.01),

                        // room password textField
                        SizedBox(
                          width: MediaQuery.of(context).size.width * 0.85,
                          child: TextField(
                            obscureText: true,
                            controller: roomPasswordController,
                            decoration: InputDecoration(
                                filled: true,
                                fillColor: whitePrimary,
                                border: OutlineInputBorder(
                                    borderRadius: BorderRadius.circular(12),
                                    borderSide: BorderSide.none),
                                hintText:
                                    'Leave blank if the room has no password',
                                hintStyle: const TextStyle(
                                    color: Color.fromARGB(255, 174, 173, 173))),
                          ),
                        ),

...

Solution

  • You can also use hooks (flutter_hooks package) and use HookConsumerWidget. Then your code will be even shorter. You will also need a package hooks_riverpod:

    class MainPage extends HookConsumerWidget {
      const MainPage({super.key});
    
      @override
      Widget build(BuildContext context, ref) {
    
        final roomListData = ref.watch(roomDataProvider);
    
        final roomIDController = useTextEditingController();
        final roomPasswordController = useTextEditingController();
    
        return Scaffold(...);
      }
    }
    

    Hooks take care of the lifecycle of objects themselves, so you don't have to manually dispose of them via the dispose method.

    Links: