skip to Main Content

I uploaded 3 pages of related code here. My problem is this: I press the Pick Country button and select a country, but I can’t display my screen the phoneCode parameter of the country I selected.

I’m working with flutter_riverpod package and my class type is ConsumerWidget.
So,I can’t use the setState() command for this class.

I added a debugPrint to my void pickCountry() function. In this way, when I press the Pick Country button, I can see that the relevant value changes in the Debug Console section.
My problem is that this value does not change on the screen.

Here is my problem on screen

all_providers.dart

final phoneControllerProvider =
    StateProvider<TextEditingController>((ref) => TextEditingController());

final countryProvider = StateProvider<Country?>((ref) => null);

country_code_and_text_field.dart //My Text Widget is here.


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

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final phoneController = ref.watch(phoneControllerProvider.notifier);
    final Country? country = ref.watch(countryProvider.notifier).state;

    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        if (country != null)
          Text(
              '+${country.phoneCode}', // The part that needs to be updated according to the country I have selected.
            style: const TextStyle(color: Colors.white),
          )
        else
          const Text(
            '00',
            style: TextStyle(color: Colors.white),
          ),
        SizedBox(
          width: ScreenSize.getWidth(context) * 0.6,
          child: TextField(
            controller: phoneController.state,
            decoration: const InputDecoration(
              hintText: 'Enter your phone number',
              hintStyle: TextStyle(color: Colors.grey),
            ),
          ),
        ),
      ],
    );
  }
}

login_page.dart // My Pick Country button is here.

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

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    Country? currentCountry = ref.read(countryProvider.notifier).state;

    void pickCountry() {
      showCountryPicker(
        context: context,
        onSelect: (Country selectedCountry) {
          currentCountry = selectedCountry;
        },
      );
      debugPrint('selected phone code: ${currentCountry?.phoneCode}');
    }

    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text(
          'Enter your phone number',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          const Text(
            'Chattor will need to verify your phone number',
            style: TextStyle(color: Colors.grey),
          ),
          TextButton(
            onPressed: pickCountry,
            child: const Text(
              'Pick Country',
              style: TextStyle(color: Colors.amber),
            ),
          ),
          const CountryCodeAndTextField(),
          SizedBox(height: ScreenSize.getHeight(context) * 0.63),
          SizedBox(
            width: ScreenSize.getWidth(context) * 0.30,
            height: ScreenSize.getHeight(context) * 0.07,
            child: const NextButtonWidget(),
          ),
        ],
      ),
    );
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    I think I need to use StateNotifierProvider instead of StateProvider to trigger the build method and change the screen in the flutter_riverpod package.

    class CountryNotifier extends StateNotifier<Country?> {
      CountryNotifier() : super(null);
    
      void setCountry(Country newCountry) {
        state = newCountry;
      }
    }
    
    final countryProvider = StateNotifierProvider<CountryNotifier, Country?>((ref) {
      return CountryNotifier();
    });
    
    void pickCountry() {
          showCountryPicker(
            context: context,
            onSelect: (Country selectedCountry) {
              ref.read(countryProvider.notifier).setCountry(selectedCountry);
            },
          );
        }
    

    After making these adjustments, my problem was solved.


  2. The challenge for me to help you, is that you do not provide a code that I can run and then see the problem — and try to fix it. So I tried to reproduce what you are doing in the following code (that you can copy and paste – and run, so you can see what it achieves and what it does not achieve).
    You can see how with the help of Riverpod "picking a country" in a drop down menu actually does change the number presented in the next line. Is this what was missing?
    If this solves your problem – great! 🙂
    If this does NOT solve your problem, then it might nonetheless help us 😉 : It could be helpful for you to describe the challenge that you face more, so that I or others here could better understand it: Could you try to use my code, implement your approach in the most condensed form possible, and let us know what’s not working — and share that with us, so we can look at it and try to find out more?

    Here is my take:

    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    
    class Country {
      const Country({required this.name, required this.numbers});
    
      final String name;
      final double numbers;
    }
    
    const _countryCodes = [
      Country(name: 'Pick Country', numbers: 0),
      Country(name: 'US', numbers: 1),
      Country(name: 'Mexico', numbers: 52),
      Country(name: 'Brazil', numbers: 55),
    ];
    
    final countryStateProvider = StateProvider<Country>((ref) => _countryCodes[0]);
    
    class MyHomePage extends ConsumerWidget {
      const MyHomePage({super.key});
    
      @override
      Widget build(BuildContext context, WidgetRef ref) {
        return Scaffold(
          body: Center(
            child: SizedBox(
              width: 500,
              child: Column(
                children: [
                  const Text('Enter your phone number'),
                  const Text('Chatter will need to verify your phone number.'),
                  const SizedBox(height: 50),
                  DropdownButton<Country>(
                    value: ref.watch(countryStateProvider),
                    onChanged: (value) =>
                        ref.read(countryStateProvider.notifier).state = value!,
                    items: _countryCodes
                        .map((country) => DropdownMenuItem(
                              value: country,
                              child: Text('${country.name}, +${country.numbers}'),
                            ))
                        .toList(),
                  ),
                  const SizedBox(height: 50),
                  Row(
                    children: [
                      Text('+${ref.watch(countryStateProvider).numbers}'),
                      const SizedBox(width: 20),
                      if (ref.watch(countryStateProvider).numbers == 0)
                        const Text('no country selected'),
                      if (ref.watch(countryStateProvider).numbers != 0)
                        Text(ref.watch(countryStateProvider).name)
                    ],
                  )
                ],
              ),
            ),
          ),
        );
      }
    }
    
    void main() => runApp(const ProviderScope(child: MyApp()));
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) => const MaterialApp(
            home: MyHomePage(),
          );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search