Flutter useEffect监听值变化仅触发一次问题及正确实现问询
你遇到的问题核心是useEffect依赖数组的触发逻辑与无差别状态修改导致的重复执行干扰:
初始化阶段:
ephemeralStateText.value初始为"init value",useEffect 触发后将其改为"value by useEffect",状态变化触发组件重建。此时 useEffect 的依赖从"init value"变为"value by useEffect",因依赖差异,useEffect 会再次执行,但这次修改的是相同值,状态无变化,组件停止重建。首次点击按钮:状态变为
"value by onPress",依赖数组变化,useEffect 触发并将状态改回"value by useEffect",再次触发组件重建。此时依赖又变为"value by useEffect",与上一次的"value by onPress"不同,useEffect 再次执行,但修改的是相同值,无状态变化。后续点击时,状态从
"value by useEffect"变回"value by onPress",useEffect 其实仍会触发,但触发后修改状态导致自身再次执行——第二次执行时因状态值未变化,没有可见UI更新,让你误以为 useEffect 被忽略。
要让 useEffect 仅在状态变为 "value by onPress" 时执行重置逻辑,只需在 useEffect 内部增加值判断,过滤无意义的重复执行:
import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; class PlayHooks extends HookConsumerWidget { PlayHooks({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final ephemeralStateText = useState("init value"); useEffect(() { // 仅当状态被修改为目标值时,才执行重置操作 if (ephemeralStateText.value == "value by onPress") { debugPrint("useEffect triggered."); ephemeralStateText.value = "value by useEffect"; } return; }, [ephemeralStateText.value]); return Scaffold( appBar: AppBar(title: Text("play hooks")), body: Center( child: Column(children: [ Text("ephemeral state text is ${ephemeralStateText.value}"), ElevatedButton( onPressed: () => ephemeralStateText.value = "value by onPress", child: Text("change ephemeral state text")), ]), ), ); } }
如果想要完全避免“状态短暂显示为 onPress”的情况,也可以直接在按钮点击事件中拦截修改(比如点击时直接设置为目标值),但上述方案已经精准实现了“每次响应特定属性变化”的需求。
内容的提问来源于stack exchange,提问作者Sho

