Flutter使用TextEditingController传值给自定义组件得到空值如何解决?
问题原因
你传递给PublishAction的_topicController.text和_messageController.text是组件首次构建时的静态值,此时输入框无用户输入,拿到的是空字符串。后续输入内容时,只要父组件没有触发重绘(未调用setState),PublishAction的入参就不会更新,内部存储的topic和message一直是初始空值。
解决方案
方案1:向PublishAction传递TextEditingController(推荐,性能最优)
点击按钮时再读取控制器的最新值,不需要触发组件重绘。
修改PublishAction定义:
class PublishAction extends StatelessWidget { final TextEditingController topicController; final TextEditingController messageController; const PublishAction({ Key? key, required this.topicController, required this.messageController, }) : super(key: key); @override Widget build(BuildContext context) { return FloatingActionButton( child: const Icon(Icons.send), onPressed: () { final topic = topicController.text; final message = messageController.text; print("topic - $topic, message - $message"); }); } }
父组件调用方式:
final _topicController = TextEditingController(); final _messageController = TextEditingController(); child: Column( children: [ TextField( controller: _topicController, decoration: const InputDecoration(labelText: "Topic"), ), TextField( controller: _messageController, decoration: const InputDecoration(labelText: "Context"), ), PublishAction( topicController: _topicController, messageController: _messageController, ), ], ),
方案2:输入时触发父组件重绘(适合简单页面)
无需修改PublishAction原有定义,在输入框内容变化时调用setState让父组件重绘,传入最新的输入值,要求父组件为StatefulWidget:
final _topicController = TextEditingController(); final _messageController = TextEditingController(); child: Column( children: [ TextField( controller: _topicController, decoration: const InputDecoration(labelText: "Topic"), onChanged: (_) => setState(() {}), ), TextField( controller: _messageController, decoration: const InputDecoration(labelText: "Context"), onChanged: (_) => setState(() {}), ), PublishAction( topic: _topicController.text, message: _messageController.text, ), ], ),
该方案每次输入都会触发子树重绘,性能略差,不适合复杂页面。
方案3:传递点击回调(推荐,耦合度最低)
将业务逻辑放到父组件处理,PublishAction仅作为按钮组件使用,无需关心输入相关逻辑:
修改PublishAction定义:
class PublishAction extends StatelessWidget { final VoidCallback onPublish; const PublishAction({ Key? key, required this.onPublish, }) : super(key: key); @override Widget build(BuildContext context) { return FloatingActionButton( child: const Icon(Icons.send), onPressed: onPublish); } }
父组件调用方式:
final _topicController = TextEditingController(); final _messageController = TextEditingController(); child: Column( children: [ TextField( controller: _topicController, decoration: const InputDecoration(labelText: "Topic"), ), TextField( controller: _messageController, decoration: const InputDecoration(labelText: "Context"), ), PublishAction( onPublish: () { final topic = _topicController.text; final message = _messageController.text; print("topic - $topic, message - $message"); }, ), ], ),
内容的提问来源于stack exchange,提问作者mushding
相关产品推荐
相关产品推荐

