Flutter Hook的useState与下拉框不起作用。

huangapple go评论60阅读模式
英文:

Flutter Hook useState not working with dropdown

问题

在选择下拉菜单的值后,useState中的值未更新。

这是我的模型类:

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

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

这是我的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,
        ),
      ],
    );
  }
}

selectedIndex的值正常工作,没有任何问题。问题出在selectedData,在更新下拉菜单后:

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

selectedIndex的值改变了,但selectedData的值一点也没变。请帮忙解决一下...

英文:

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...

答案1

得分: 2

为什么你认为它必须改变?useState(<initialData>) 中的 initialData 在第一次调用时初始化了 ValueNotifier,并在后续调用中被忽略。换句话说,selectedData 的值不会自动订阅到 selectedIndex 的值 - 它们是独立的 ValueNotifier。

如果你想缓存一个值并基于其他值(依赖项)重新计算它,请使用 useMemoized 钩子,像这样:

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

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]
),

huangapple
  • 本文由 发表于 2023年7月17日 13:56:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76701811.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定