为何添加setState后,重置带AutovalidateMode.onUserInteraction的表单会报错?
问题原因解析:点击Clear按钮出现'Missing'错误的根源
先梳理执行流程差异
无setState的正常情况:
点击Clear按钮后,代码按以下顺序执行:
- 等待
Future.delayed(Duration.zero)(仅将后续操作延后到当前同步代码执行完毕) - 调用
Form.reset():清空字段值的同时,清除所有验证错误状态 - 调用
controller.clear():同步清空控制器内容
此时AutovalidateMode.onUserInteraction不会触发验证——因为字段值是通过代码重置的,不属于用户主动交互操作,所以不会调用validator,错误自然不会显示。
开启setState后的异常情况:
点击Clear按钮后,执行流程被打乱:
- 调用
setState(() {}):标记当前State需要重建,框架将重建任务加入事件队列 - 等待
Future.delayed(Duration.zero):这个延迟会把后续的reset和clear操作延后到下一个事件循环,在此期间框架会优先执行State重建 - 重建Widget树:新生成的
TextFormField关联原控制器(此时控制器内容还是输入的2个字符),原表单的验证状态('Too short')也被保留 - 延迟结束,执行
Form.reset():将字段值设为空,同时清除验证错误,但此时字段值从2个字符变为空的操作,会触发TextFormField的状态更新 - 由于
AutovalidateMode.onUserInteraction的规则,重建后的字段值变更会被误判为用户交互触发的修改,进而调用validator,此时输入为空,就会返回'Missing'错误 - 最后执行
controller.clear(),但此时验证已经完成,错误已经显示出来
本质原因
setState触发的Widget重建打乱了表单重置和验证的时机:重建后的TextFormField会把后续代码触发的字段值清空操作,错误地识别为用户交互行为,从而触发onUserInteraction模式下的验证,最终显示空值错误。
内容的提问来源于stack exchange,提问作者iDecode
相关产品推荐
相关产品推荐

