flutterflutter-hooks

Flutter Hook useState not working with dropdown


After choosing a value from dropdown, the value in useState does not update.

This is my model class

class Data {
  final int id;
  final String name;
  final String someOtherData;

  Data({
    required this.id,
    required this.name,
    required this.someOtherData,
  });

}

This is my HookWidget

class Demo extends HookWidget {
  Demo({super.key});

  final data = [
    Data(id: 0, name: 'please pick one', someOtherData: 'no value'),
    Data(id: 10, name: 'ten', someOtherData: 'tenten'),
    Data(id: 20, name: 'twenty', someOtherData: 'twentytwenty'),
  ];

  @override
  Widget build(BuildContext context) {
    final selectedIndex = useState(0);
    final selectedData = useState(
      data.where((element) => element.id == selectedIndex.value).first,
    );

    return  Column(
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: [
          DropdownButton(
            value: selectedIndex.value,
            items: data
                    .map(
                      (e) => DropdownMenuItem(
                        value: e.id,
                        child: Text(
                          e.name,
                        ),
                      ),
                    )
                    .toList(),
                onChanged: (value) => selectedIndex.value = value!,
              ),
              Text(
                selectedData.value.someOtherData,
              ),
            ],
        );
      }
    }

Value of selectedIndex works fine, no problem at all. The problem is with selectedData, after updating the dropdown

onChanged: (value) => selectedIndex.value = value!,

selectedIndex value changed, but selectedData value doesn't change at all. Help please...


Solution

  • Why do you think it must change? The initialData in useState(<initialData>) initializes the ValueNotifier on the first call and is ignored on subsequent calls. In other words, the value of selectedData is not automatically subscribed to the value of selectedIndex – they are separate ValueNotifier-s.

    If you want to cache a value and recalculate it based on some other values (dependencies) use the useMemoized hook instead, like so:

    final selectedIndex = useState(0);
    final selectedData = useMemoized(
    () => data[selectedIndex.value],
    [selectedIndex.value]
    ),