首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Flutter Hooks使用构建期间调用的useEffect - setState()或markNeedsBuild()获取数据

Flutter Hooks 是 Flutter 框架中引入的一种新特性,它允许开发者在函数组件中使用状态和生命周期特性,而不需要转换为 StatefulWidget。useEffect 是 Flutter Hooks 中的一个核心 API,类似于 React 中的 useEffect,它允许你在组件渲染之后执行一些代码,比如数据获取、订阅等。

基础概念

  • useEffect: 用于处理副作用操作,比如数据获取、订阅或手动更改 DOM 等。
  • setState(): 用于通知 Flutter 框架,组件的状态已经改变,需要重新调用 build 方法来更新 UI。
  • markNeedsBuild(): 用于标记组件需要重建,Flutter 框架会在下一个事件循环中调用 build 方法。

相关优势

  • 简化代码: 使用 Hooks 可以减少样板代码,使得函数组件更加简洁。
  • 更好的性能: Hooks 允许更细粒度的控制组件的更新,从而提高应用性能。
  • 易于维护: 代码结构更清晰,易于理解和维护。

类型

useEffect 接受两个参数:一个执行副作用的函数和一个依赖数组。当依赖数组中的值发生变化时,副作用函数会被执行。

应用场景

  • 数据获取: 在组件挂载后获取数据,并更新状态。
  • 订阅: 订阅某个事件或数据流,并在组件卸载时取消订阅。
  • 手动更改 UI: 在某些情况下,可能需要手动触发 UI 的更新。

示例代码

代码语言:txt
复制
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('useEffect Example')),
        body: DataFetchingWidget(),
      ),
    );
  }
}

class DataFetchingWidget extends StatefulWidget {
  @override
  _DataFetchingWidgetState createState() => _DataFetchingWidgetState();
}

class _DataFetchingWidgetState extends State<DataFetchingWidget> {
  String _data = 'Loading...';

  @override
  void initState() {
    super.initState();
    // 初始化时获取数据
    fetchData();
  }

  void fetchData() async {
    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      _data = 'Data Fetched!';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(child: Text(_data));
  }
}

遇到的问题及解决方法

问题:为什么在 useEffect 中调用 setState()markNeedsBuild() 会导致无限循环?

原因:当 useEffect 的依赖数组中包含了状态变量,并且在 useEffect 中调用 setState()markNeedsBuild() 时,会触发组件的重新渲染,从而导致 useEffect 再次执行,形成无限循环。

解决方法

  1. 确保 useEffect 的依赖数组中不包含会导致 setState()markNeeds规范Build() 调用的状态变量。
  2. 如果需要在 useEffect 中调用 setState()markNeedsBuild(),可以考虑使用 useRef 来存储需要更新的状态,而不是直接使用状态变量。
代码语言:txt
复制
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('useEffect Example')),
        body: DataFetchingWidget(),
      ),
    );
  }
}

class DataFetchingWidget extends StatefulWidget {
  @override
  _DataFetchingWidgetState createState() => _DataFetchingWidgetState();
}

class _DataFetchingWidgetState extends State<DataFetchingWidget> {
  String _data = 'Loading...';
  final _dataRef = GlobalKey();

  @override
  void initState() {
    super.initState();
    // 初始化时获取数据
    fetchData();
  }

  void fetchData() async {
    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      _dataRef.currentState?.setState(() {
        _data = 'Data Fetched!';
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(_data),
      key: _dataRef,
    );
  }
}

参考链接

通过以上内容,你应该能够更好地理解 Flutter Hooks 中 useEffect 的使用,以及如何正确地处理数据获取和状态更新。

相关搜索:Flutter -构建期间调用的setState()或markNeedsBuild()Flutter:在使用Provider构建期间调用的setState()或markNeedsBuild()在构建期间调用setState()或markNeedsBuildTextFormField:构建期间调用的setState()或markNeedsBuild()在StreamBuilder内部构建期间调用setState()或markNeedsBuild()收到错误“在构建期间调用了setState()或markNeedsBuild()”在构建期间调用setState()或markNeedsBuild(),在Flutter中使用FutureBuilder中的Provider和StreamBuilder在使用提供程序生成期间调用setState()或markNeedsBuild()Flutter Provider - setstate或markneedsbuild()在构建过程中调用Flutter Provider带有listen false,但仍然得到错误"setState()或markNeedsBuild()在构建期间被调用“。在构建期间调用setState()或markNeedsBuild()。尝试在flutter中创建一个简单的计时器在构建期间调用setState()或markNeedsBuild()。将GestureDetector放入容器中重构AKA后出错在构建期间调用setState()或markNeedsBuild()。导致小部件的相关错误是RoundIconButton。A RenderFlex溢出未处理的异常:在生成期间调用了setState()或markNeedsBuild()。BlocListener内幕显示和隐藏小部件生成错误期间调用的SetState()或markNeedsBuild()颤动显示对话框在构建过程中调用的setState()或markNeedsBuild()在构建过程中调用的setState()或markNeedsBuild() -何时设置从API获取的变量的值?如何从react hooks或useEffect获取新的更新数据?调试断言期间调用的setState()或markNeedsBuild():第4134行位置12:‘!_ build....Failed’:不为真将数据传递给生成过程中调用的provider - setState()或markNeedsBuild()
相关搜索:
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Flutter Hooks 使用及原理

同样的,我们也可以在Flutter中使用Hooks。Hooks对于从事Native开发的开发者可能比较陌生。...React定义了一些常用的Hooks函数,如useState,useEffect等等。 useState useState我们可能会比较常用,用来获取当前Widget所需要的状态。...useEffect 在首次创建MySotre实例之后我们一般需要做一些初始化工作,例如开始加载数据之类。有时候或许在Widget生命周期结束的时候做一些清理工作。...这个函数由其子类实现;如果不保留状态,那就调用_createHookState重新获取一个状态实例把原来的给替换掉。...总结 从以上对flutter_hooks的介绍可以看出,使用Hooks可以大大简化我们的开发工作,但是要注意一点,flutter_hooks并不能处理在Widget之间传递状态这种情况,这时就需要将Hooks

2.4K30

StatefulWidget与State

Widget,但是StatefulWidget没有build方法,所以它只能使用State的build来构建Widget。...,或热重载时,系统会回调该方法 void didUpdateWidget(covariant T oldWidget) {}//重新载入 void reassemble() {}//设置界面数据变更...setState如何触发界面变更 在前面很多例子中我们多次使用到setState方法,来更新Element中的数据,每次当每次数据变更时我们触发setState方法,紧接着界面就跟着变化了,大家应该都知道这是...调用Element的markNeedsBuild方法 上面的1-5步流程都非常的简单,在第6步调用markNeedsBuild方法。...小结 StatefulWidget是由状态组建,我们可以使用setState方法来重新构建组建 StatefulWidget的Wdiget是通过State的Build方法构建的 setState方法将要重新构建的

1.4K10
  • Flutter的setState更新原理和流程

    分析 Flutter状态类: StatelessWidget:无状态类,没有状态更新,界面一经创建无法更改; StatefulWidget:有状态类,当状态改变,调用setState()方法会触发StatefulWidget...也就是只有当我们的类是有状态类的时候才能进行状态刷新,setState也是在State(有状态类)类里 解析 :framework.dart文件State类 调用 setState() 必须是没有调用过..._element.markNeedsBuild(); } setState方法除了一些条件判断就是:_element.markNeedsBuild();那我们看看markNeedsBuild。...BuildOwner 类 scheduleBuildFor方法 BuildOwner类是widget framework的管理类,它跟踪那些需要重新构建的 widget。..._active=false 的时候直接返回 管理类 1.告诉管理类方法自己需要被重新构建: owner.scheduleBuildFor(this) 调用 window.scheduleFrame()

    80920

    Widget的生命周期和渲染原理

    我下面可以稍微罗列一下: 内存管理相关,比如销毁数据、销毁监听者、销毁timer 初始化数据,比如发送网络请求,创建一些数据等 一般而言,Flutter的widget分为StatefulWidget和...我们知道,在需要修改数据更新UI的时候,只要调用setState然后在其中更改数据,这样UI就可以随之改变了,这是因为setState函数可以触发widget的销毁重建,也就是会触发state的build...好,现在我们知道了通过setState来根据数据自动调整UI的原理了,因此,原则上我们是可以不调用setState而直接给element调用markNeedsBuild函数来实现UI的更新,即: 在StatefulWidget...的build方法中将context转成StatefulElement类型的element,然后直接在对应的数据更新完了之后,手动调用element.markNeedsBuild(),这样就能够实现UI的更新了...Widget的渲染原理 关于Widget的渲染,我在Widget,构建Flutter界面的基石中有过介绍,本文也是依次为基准,再做一些拓展介绍。

    1.3K20

    Flutter 组件集录 | InheritedNotifier 内置状态管理组件

    ; } } 然后在想要更新数据的上层节点,套上 DownloadDataScope 组件,这样数据就可以在子树节点中被共享: 使用时就非常方便,通过静态方法 of 根据上下文获取可监听对象即可。...可以看到 DetailProgressView 此时可以是 StatelessWidget , 但依然会被通知,从而重新构建。这是一种非 State#setState 更新状态的方式。...:使用了 of 获取数据的组件,在可监听对象发生通知时会触发重新构建。...了解 Flutter 框架的都知道 State#setState 本质上也就是触发了持有 Element 的 markNeedsBuild 方法。...如下所示,此时其中是 HomeProgressView 对应的元素: 也就是说,接下来 HomeProgressView 对应的元素触发 didChangeDependencies,其中调用了 markNeedsBuild

    31420

    React Hooks 万字总结

    更符合 FP 的理解, React 组件本身的定位就是函数,一个吃进数据、吐出 UI 的函数 常用 hook useState const [state, setState] = useState...(initialState) useState 有一个参数,该参数可以为任意数据类型,一般用作默认值 useState 返回值为一个数组,数组的第一个参数为我们需要使用的 state,第二个参数为一个...: 只在 React 函数中调用 Hook; 不要在循环、条件或嵌套函数中调用 Hook。...== null) { // 获取Hook对象上的 queue,内部存有本次更新的一系列数据 const firstRenderPhaseUpdate =...,调用的 hook 的只有一个 setSex 所以总结一下初始化阶段构建链表,更新阶段按照顺序去遍历之前构建好的链表,取出对应的数据信息进行渲染当两次顺序不一样的时候就会造成渲染上的差异。

    94420

    React Hooks 是什么

    React Hooks 使用 function 组件的写法,通过 useState 这样的 API 解决了 function 组件没有 state 的问题,通过 useEffect 来解决生命周期的问题...由于 setState 使用函数式的更新方式,所以可以传递函数给 setState,该函数将接收先前的值,并返回更新的值。...return initialState; }); initialState 参数只有在初始渲染期间才会使用,在随后的渲染中,它会被忽略。...之前,我们需要在 componentDidMount 和 componentDidUpdate 中同时去调用更改 title 的方法,以完成组件初始化的状态和数据更新的状态。...只在顶层调用 Hooks Hooks 只能在顶层调用,不要在循环,条件或嵌套函数中调用 Hook。原因是 React 需要保证每次组件渲染的时候都以相同的顺序调用 Hooks。

    3.2K20

    Flutter | 启动,渲染,setState 流程

    组件树在构建完毕后,回到 runApp 的实现中,当调完 attachRootWidget 后,最后一行会调用 WidgetsFlutterBainding 实例的 scheduleWarmUpFrame...上屏,会将绘制出的bit数据发送给GPU .....///// } } 复制代码 可以到上面代码主要做了五件事: 1,重新构建 widget 树(buildScope()) 2,更新布局(flushLayout..._inDirtyList = true; } 复制代码 当调用 setState 后: 1,首先调用 markNeedsBuild 方法,将 element 的 dirty 标记为 true,表示需要重建...到此,setState 中最核心的就是触发了一个 请求,在下一次屏幕刷新的时候就会回调 onBeginFrame,执行完成之后才会调用 onDrawFrame 方法。...上屏,会将绘制出的bit数据发送给GPU .....///// } } 复制代码 以上,便是 setState 调用的大概过程,实际的流程会更加复杂一点,例如在这个过程中不允许再次调用 setState

    1.2K10

    87.精读《setState 做了什么》

    2 概述 setState 函数是在 React.Component 组件中调用的,所以最自然的联想是,更新 DOM 的逻辑在 react 包中实现。...setState 怎么调用平台实现 每个平台对 UI 更新逻辑的实现,会封装在 updater 函数里,所以不同平台代码会为组件添加各自的 updater 实现: // Inside React DOM...,因为这个 API 是由 react 引擎在 setState 时调用的: // A bit simplified setState(partialState, callback) { // Use...Hooks Hooks 的原理与 setState 类似,当调用 useState 或 useEffect 时,其内部调用如下: // In React (simplified a bit) const...通用数据查询服务 通用数据查询服务也比较流行,通过磨平各数据库语法,让用户通过一套 SQL 查询各种类型数据库的数据。

    73620

    为啥Flutter Hooks没有受到太多关注和青睐?

    在本文中,我会试着告诉大家如何使用 Flutter Hooks 来减少样板代码,并基本上摆脱你现在用的几乎所有有状态小部件(StatefulWidget),让大家知道 Hooks 用起来是多么简单利落!...换句话说了解 Flutter Hooks 并不需要 React 的相关知识。 Hooks 是一种与多个小部件共享同一代码的方法,这些代码往往是在有状态小部件之间重复或难以共享的代码。...这里 Flutter Hooks 的优势并不大,但一般来说,当你希望初始化对象以加载数据的时候,用 Hooks 也是可以做到的。现在让我们看看 useEffect 。...Effect Hook 如前所述,我们要加载数据,为此一般会在 initState 上调用一个方法。...定制 Hooks flutter_hooks 包提供了两种自定义 Hooks 的方法,只需使用一个函数或创建一个自定义类即可。

    1.2K20

    【 Flutter 极限测试】连续 1000000 次 setState 会怎么样

    测试描述 可能很多人会认为,每次的 State#setState 都会触发当前状态类的 build 方法重新构建。但真的是这样吗,你真的了解 Flutter 界面的更新流程吗?...另外,本文有对应的视频版,可在 哔哩哔哩 进行观看: 【Flutter极限测试 - 连续 setState 1000000 次会怎么样?...源码调试分析 如下,在 State#setState 源码中可以看出,它只做了两件事: 触发入参回调 fn 。 执行持有元素的 markNeedsBuild 方法。...总的来说, State#setState 的核心作用就是把持有的元素标脏并申请新帧调度。而只有新帧到来,执行完构建之后,元素的 dirty 才会置为 false 。...也就是说,两帧之间,无论调用多少次 setState ,都只会触发一次, 元素标脏 和 申请新帧调度 。这就是为什么连续触发 1000000 次,并无大事发生的原因。

    69130

    谈一谈我对React Hooks的理解

    日常开发中会经常使用的React的Hooks,useEffect、useState会不会使你感到疑惑?...数据获取、订阅或手动修改DOM都属于副作用(side effects)。...0x01 构建React Hooks的心智模型 个人在一开始接触react hooks的时候,觉得代码的执行有点违背常识,在对react构建合理的心智模型花了不少时间。...不过在后来不断地学习以及运用之后,我个人觉得hooks其实是一种非常轻量的方式,在项目构建中,开发自定义的hooks,然后在应用程序中任意地方调用hook,类似于插件化(可插拔)开发,降低了代码的耦合度...那么在开发过程中,我们会尝试在组件载入时候,通过api获取远程数据,并运用于组件的数据渲染,所以我们使用了如下的一个简单例子: useEffect(() => { featchData(); },

    1.2K20

    换个角度思考 React Hooks

    其中 return 的函数是在 useEffect 再次执行前或是组件要销毁时执行,由于闭包,useEffect 中的返回函数可以很容易地获取对象并清除订阅。...使用 useEffect 进行数据的处理; 存储变量到 state; 在 JSX 中引用 state。 有没有发现中间多了个 state 的环节?...因为函数组件中 render 和生命周期钩子在同一个函数作用域中,这也就意味着不再需要 state 作中间数据桥梁,我们可以直接在函数执行时获取到处理的数据,然后在 return 的 JSX 中使用,不必需要每次使用属性都要在...而观察类组件的代码,我们可以发现其使用了大量的陈述性代码,例如判断是否相等,同时还使用了 state 作为数据的存储和使用,所以产生了很多 setState 代码以及增加了多次重新渲染。...在 Hooks 开发中,我们把这些琐碎的负担都清除了,只需关注要同步的变量。 所以当数据关系复杂起来的时候,类组件的这种写法显得比较笨重,使用 Hooks 的优势也就体现出来了。

    4.8K20

    腾讯前端经典react面试题汇总

    注意:避免在 循环/条件判断/嵌套函数 中调用 hooks,保证调用顺序的稳定;只有 函数定义组件 和 hooks 可以调用 hooks,避免在 类组件 或者 普通函数 中调用;不能在useEffect...用法与useEffect类似,只是区别于执行时间点的不同useEffect属于异步执行,并不会等待 DOM 真正渲染后执行,而useLayoutEffect则会真正渲染后才触发;可以获取更新后的 state...componentWillReceiveProps调用时机已经被废弃掉当props改变的时候才调用,子组件第二次接收到props的时候如何用 React构建( build)生产模式?...然后用新的树和旧的树进行比较,记 录两棵树差异;把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。setState方法的第二个参数有什么用?使用它的目的是什么?...它是一个回调函数,当 setState方法执行结束并重新渲染该组件时调用它。在工作中,更好的方式是使用 React组件生命周期之——“存在期”的生命周期方法,而不是依赖这个回调函数。

    2.1K20

    面试官最喜欢问的几个react相关问题

    它具有以下特点:异步与同步: setState并不是单纯的异步或同步,这其实与调用时的环境相关:在合成事件 和 生命周期钩子 (除 componentDidUpdate) 中,setState是"异步...,传入的函数将会被 顺序调用;注意事项:setState 合并,在 合成事件 和 生命周期钩子 中多次连续调用会被优化为一次;当组件已被销毁,如果再次调用setState,React 会报错警告,通常有两种解决办法将数据挂载到外部...注意:避免在 循环/条件判断/嵌套函数 中调用 hooks,保证调用顺序的稳定;只有 函数定义组件 和 hooks 可以调用 hooks,避免在 类组件 或者 普通函数 中调用;不能在useEffect...如下所示, username没有存储在DOM元素内,而是存储在组件的状态中。每次要更新 username时,就要调用 setState更新状态;每次要获取 username的值,就要获取组件状态值。...当要获取表单数据时,要首先获取表单元素,然后通过表单元素获取元素的值。注意:为了方便在组件中获取表单元素,通常为元素设置ref属性,在组件内部通过refs属性获取对应的DOM元素。

    4K20
    领券