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

使用getDerivedStateFromProps获取API数据会导致组件多次呈现。

getDerivedStateFromProps 是 React 类组件中的一个生命周期方法,它在组件实例化后以及每次重新渲染前都会被调用。这个方法的主要用途是根据新的 props 来更新组件的 state。然而,如果不正确地使用它,确实可能导致组件不必要的多次渲染。

基础概念

getDerivedStateFromProps 接收两个参数:nextPropsprevState,并返回一个对象来更新 state,或者返回 null 表示不更新 state。

为什么会导致多次呈现?

当组件挂载后,每次父组件的更新导致子组件重新渲染时,getDerivedStateFromProps 都会被调用。如果在 getDerivedStateFromProps 中发起 API 请求,并且基于请求结果更新 state,那么可能会出现以下情况:

  1. 组件首次渲染。
  2. getDerivedStateFromProps 被调用,发起 API 请求。
  3. API 请求返回前,组件可能因为其他原因(如父组件更新)再次渲染。
  4. getDerivedStateFromProps 再次被调用,再次发起 API 请求。
  5. 这个过程可能会重复,导致多次不必要的渲染和 API 请求。

如何解决这个问题?

为了避免这种情况,可以采取以下策略:

  1. 使用 componentDidMount 发起 API 请求:这是最常见的做法,因为 componentDidMount 只在组件挂载后调用一次。
代码语言:txt
复制
class MyComponent extends React.Component {
  state = {
    data: null,
  };

  componentDidMount() {
    fetch('api-url')
      .then(response => response.json())
      .then(data => this.setState({ data }));
  }

  render() {
    return <div>{this.state.data ? this.state.data : 'Loading...'}</div>;
  }
}
  1. 使用 React 的 useEffect 钩子(如果是函数组件)useEffect 允许你在组件挂载后执行副作用操作,并且可以通过返回一个清理函数来处理组件卸载时的逻辑。
代码语言:txt
复制
import React, { useState, useEffect } from 'react';

function MyComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    let isMounted = true;

    fetch('api-url')
      .then(response => response.json())
      .then(data => {
        if (isMounted) {
          setData(data);
        }
      });

    return () => {
      isMounted = false;
    };
  }, []); // 空依赖数组确保只在组件挂载时执行一次

  return <div>{data ? data : 'Loading...'}</div>;
}
  1. 使用状态管理库:如 Redux 或 MobX,这些库提供了更精细的状态管理,可以帮助你更好地控制何时以及如何获取和更新数据。

应用场景

  • 当你需要在组件挂载后立即获取数据,并且不需要在每次 props 更新时都重新获取数据时。
  • 当你需要根据外部数据源的变化来更新组件状态,但又不希望因为组件的其他渲染而导致重复的数据请求时。

总结

getDerivedStateFromProps 是一个强大的工具,但需要谨慎使用以避免不必要的性能开销。通常情况下,推荐使用 componentDidMountuseEffect 来处理组件挂载时的数据获取逻辑。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

谈谈新的 React 新的生命周期钩子

React 的生命周期 API 一直以来十分稳定,但是当 React 团队在引入异步渲染机制的时候,发现之前的生命周期会的使用产生一些问题,所以才会改动生命周期 API,感兴趣的可以看这篇博客。...为何移除 componentWillMount 因为在 React 未来的版本中,异步渲染机制可能会导致单个组件实例可以多次调用该方法。...Listener,更有可能导致内存泄漏 发出重复的异步网络请求,导致 IO 资源被浪费 在服务端渲染时,componentWillMount 会被调用,但是会因忽略异步获取的数据而浪费 IO 资源 现在...和 componentDidUpdate 执行前后可能会间隔很长时间,足够使用户进行交互操作更改当前组件的状态,这样可能会导致难以追踪的 BUG。...和 componentDidUpdate 配合使用时将组件临时的状态数据存在组件实例上浪费内存,getSnapshotBeforeUpdate 返回的数据在 componentDidUpdate 中用完即被销毁

1K20
  • 前端开发常见面试题,有参考答案

    被废弃的三个函数都是在render之前,因为fber的出现,很可能因为高优先级任务的出现而打断现有任务导致它们会被执行多次。...,如果在 willMount 中订阅事件,但在服务端这并不会执行 willUnMount事件,也就是说服务端会导致内存泄漏所以componentWilIMount完全可以不使用,但使用者有时候难免因为各...这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,另一方面也会增加组件的重绘次数。...使用了 Redux,所有的组件都可以从 store 中获取到所需的 state,他们也能从store 获取到 state 的改变。这比组件之间互相传递数据清晰明朗的多。...什么是受控组件和非受控组件受控组件: 没有维持自己的状态 数据由付组件控制 通过props获取当前值,然后通过回调函数通知更改非受控组件 保持这个自己的状态 数据有DOM控制 refs用于获取其当前值

    1.3K20

    第三篇:为什么 React 16 要更改组件的生命周期?(下)

    getDerivedStateFromProps 里面做任何类似于 this.fetch()、不合理的 this.setState(会导致死循环的那种)这类可能会产生副作用的操作。...这个需求的前半截要求我们对比更新前后的数据(感知变化),后半截则需要获取真实的 DOM 信息(获取位置),这时用 getSnapshotBeforeUpdate 来解决就再合适不过了。...componentWillMount 结束后,render 会迅速地被触发,所以说首次渲染依然会在数据返回之前执行。...这样做不仅没有达到你预想的目的,还会导致服务端渲染场景下的冗余请求等额外问题,得不偿失。 2. 在 Fiber 带来的异步渲染机制下,可能会导致非常严重的 Bug。...但实际却可能因为 componentWillxxx 被打断 + 重启多次而多次调用付款接口,最终付了 50 块钱;又或者你可能会习惯在 componentWillReceiveProps 里操作 DOM

    1.2K20

    React生命周期简单分析

    在服务端渲染时 componentDidMount 是不会被调用的,只会调用componentWillMount. 2.在componentWillMount中, 我们一般会用来异步获取数据, 但是在新版生命周期中...如果需要从远端加载数据的话, 推荐在这个方法中初始化 由于这个方法发生初始化挂载render方法之后, 因此在这个方法中调用setState()会导致一次额外的渲染, 只不过这次渲染会发生在浏览器更新屏幕之前...这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,也会增加组件的重绘次数. // App.jsx // 在其中添加上static getDerivedStateFromProps...另外,虽然this.setState()也会导致组件重新渲染,但并不会导致这个方法的重新调用....要使用context的数据,我们需要使用Consumer组件 // 数据提供者 class App extends React.Component { render() {

    1.2K10

    React 特性剪辑(版本 16.0 ~ 16.9)

    开启 Fiber 后,获取异步数据的方法应放到 render 后面的生命周期钩子里(phase 2 阶段)进行, 因为 render 前面的生命周期钩子(phase 1阶段)会被执行多次 注意:...在此之前的实现方式是 react-loadable 并发模式(16.8, 2019 年 Q2 季度): 在文件懒加载的同时能做其它交互; data fetching(16.9 版本, 2019 年中): 数据动态呈现...Context(16.3、16.6) Context 相当于是用组件化的方式使用 global, 使用其可以共享认证的用户、首选语言(国际化)等一些全局的信息, 而不必通过组件一层层传递。...基于以下两点考虑: 服务端渲染: 在服务端渲染的情景下, componentWillMount 执行完立马执行 render 会导致 componentWillMount 里面执行的方法(获取数据,...): 移除这个 api 基于如下考虑: 语义不太契合逻辑 举个例子: 比如切换 tab 时都要重新获取当前页面的数据, 之前通常会这么做: componentWillReceiveProps(nextProps

    1.4K30

    React 组件性能优化——function component

    当 Tab 下的页面开始加载时,会去读取这个 参数,并且使用它去做一些请求,获取更多的信息进行渲染。 最初拿到这个需求时,我使用了 类组件 去开发,但实践过程中发现编写出的代码不易理解和管理。...另一个不好的 ( componentWillReceiveProps ) 上面的 中,导致我们必须使用 componentDidUpdate 的一个主要原因是,getDerivedStateFromProps...为此,我们不妨使用 componentWillReceiveProps 来实现,在获取到 props 的时候就能直接发起请求,并且 setState。...纯组件 api 对组件输入的数据进行浅层比较,如果当前输入的数据和上一次相同,那么组件就不会重新渲染。...2.2. useCallback 在函数组件中,当 props 传递了回调函数时,可能会引发子组件的重复渲染。当组件庞大时,这部分不必要的重复渲染将会导致性能问题。

    1.6K10

    React 组件性能优化——function component

    当 Tab 下的页面开始加载时,会去读取这个 参数,并且使用它去做一些请求,获取更多的信息进行渲染。 最初拿到这个需求时,我使用了 类组件 去开发,但实践过程中发现编写出的代码不易理解和管理。...另一个不好的 ( componentWillReceiveProps ) 上面的 中,导致我们必须使用 componentDidUpdate 的一个主要原因是,getDerivedStateFromProps...为此,我们不妨使用 componentWillReceiveProps 来实现,在获取到 props 的时候就能直接发起请求,并且 setState。...纯组件 api 对组件输入的数据进行浅层比较,如果当前输入的数据和上一次相同,那么组件就不会重新渲染。...2.2. useCallback 在函数组件中,当 props 传递了回调函数时,可能会引发子组件的重复渲染。当组件庞大时,这部分不必要的重复渲染将会导致性能问题。

    1.6K10

    你需要的react面试高频考察点总结

    总结:跟服务器端渲染(同构)有关系,如果在componentWillMount里面获取数据,fetch data会执行两次,一次在服务器端一次在客户端。...或收集项中的其他唯一字符串: {todos.map((todo) => {todo.text} )};在集合中添加和删除项目时,不使用键或将索引用作键会导致奇怪的行为...时,就可以考虑使用getDerivedStateFromProps来进行替代。...React-intl提供了两种使用方法,一种是引用React组件,另一种是直接调取API,官方更加推荐在React项目中使用前者,只有在无法使用React组件的地方,才应该调用框架提供的API。...}}函数组件是无状态的(同样,小于 React 16.8版本),并返回要呈现的输出。

    3.6K30

    React Async Rendering

    一.渐进迁移计划 启用Fiber最大的难题是关键的变动会破坏现有代码,这个breaking change主要来自组件生命周期的变化: // 第1阶段 render/reconciliation componentWillMount...(引自生命周期hook | 完全理解React Fiber) 一般道德约束render是纯函数,因为明确知道render会被多次调用(数据发生变化时,再render一遍看视图结构变了没,确定是否需要向下检查...componentDidMount里发就好了,算是实践原则,不要在componentWillUnmount里发请求,之前是因为对SSR不友好,而现在有2个原因了 注意,如果是为了尽早发请求(或者SSR下希望在render之前同步获取数据...)的话,可以挪到constructor里做,同样不会多次执行,但大多数情况下(SSR除外,componentDidMount不触发),componentDidMount也不慢多少 另外,将来会提供一个suspense...开启Async Rendering后可能会造成多次监听,同样存在内存泄漏风险 这样写是因为一般认为componentWillMount和componentWillUnmount是成对儿的,但在Async

    1.5K60

    React生命周期深度完全解读

    但是它会破坏 props 数据的单一数据源。在首次渲染组件时,不会调用此生命周期钩子;使用 this.setState 触发组件更新时,也不会调用此生命周期钩子。...不过要注意:如果是父组件渲染导致了组件的重新渲染,即使传给该组件的 props 没变,该组件中的这个生命周期函数也会被调用。我们一般不使用此生命周期函数,因为它通常会破坏数据源的单一性。...不过注意:它并不会阻止子组件因为 state 改变而导致的更新。使用场景:这个生命周期方法通常用来做性能优化。...而这导致的问题就是:在 render 阶段执行的生命周期函数可能被执行多次。...父子组件生命周期函数调用顺序接下来我们来探究一下 React 中父子组件生命周期函数的执行顺序。由不同的原因导致的组件渲染,React 会执行不同的生命周期函数。

    1.9K21

    React生命周期

    (render函数和didMount函数的执行时间),但是为什么我们还要在didMount中获取数据 如果使用服务端渲染的话,willMount会在服务端和客户端各自执行一次,这会导致请求两次(接受不了...constructor代替willMount 为什么要改变生命周期 从上面的生命周期的图中可以看出,被废弃的三个函数都是在render之前,因为fiber的出现,很可能因为高优先级任务的出现而打断现有任务导致它们会被执行多次...首先这个函数的功能完全可以使用componentDidMount和constructor来代替,异步获取的数据的情况上面已经说明了,而如果抛去异步获取数据,其余的即是初始化而已,这些功能都可以在constructor...中执行,除此之外,如果我们在willMount中订阅事件,但在服务端这并不会执行willUnMount事件,也就是说服务端会导致内存泄漏 所以componentWillMount完全可以不使用,但使用者有时候难免因为各种各样的情况...这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,另一方面也会增加组件的重绘次数。

    1.8K60

    浅谈 React 生命周期

    例如,实现 组件可能很方便,该组件会比较当前组件与下一组件,以决定针对哪些组件进行转场动画。 派生状态会导致代码冗余,并使组件难以维护。...如果只想在 「prop 更改时重新计算某些数据」,请使用 memoization helper 代替。...如需通过网络请求获取数据,此处是实例化请求的好地方。 这个方法是比较适合添加订阅的地方。如果添加了订阅,请不要忘记在 componentWillUnmount() 里取消订阅。...,会导致 UI 界面多次更改渲染,这是绝对要避免的问题。...而如果开发者在这些函数中运行了副作用(或者操作 DOM),那么副作用函数就有可能会被多次重复执行,会带来意料之外的严重 bug。

    2.3K20

    React16废弃的生命周期和新的生命周期

    will: componentWillMount componentWillReceiveProps componentWillUpdate 废弃的原因:是在React16的Fiber架构中,调和过程会多次执行...此外,多次执行,在周期中如果有setState或dom操作,会触发多次重绘,影响性能,也会导致数据错乱。 2....React16的2个新的生命周期: getDerivedStateFromProps getSnapshotBeforeUpdate 2.1 getDerivedStateFromProps的用法 这个周期很难用...: 触发时机频繁,16.3是在props变化时触发,16.4则改为在每次组件渲染器调用,即无论props变化,组件自己setState,父组件render 都会触发 静态方法,本意是隔离访问组件实例,却造成访问组件的数据和方法十分不便...,难以进行数据比较 不能setState,而是返回一个对象来更新state,使用不便,也可能触发多次更新状态 当组件实例化的时候,这个方法替代了componentWillMount(),而当接收到新的

    1.7K30

    美团前端二面常考react面试题(附答案)

    很多时候你会使用数据中的 IDs 作为 keys,当你没有稳定的 IDs 用于被渲染的 items 时,可以使用项目索引作为渲染项的 key,但这种方式并不推荐,如果 items 可以重新排序,就会导致...StrictMode 目前有助于:识别不安全的生命周期关于使用过时字符串 ref API 的警告关于使用废弃的 findDOMNode 方法的警告检测意外的副作用检测过时的 context API描述...传统的 MVC 模式在分离数据(Model)、UI(View和逻辑(Controller)方面工作得很好,但是 MVC 架构经常遇到两个主要问题:数据流不够清晰:跨视图发生的级联更新常常会导致混乱的事件网络...使用 Flux 模式的复杂用户界面不再遭受级联更新,任何给定的React 组件都能够根据 store 提供的数据重建其状态。Flux 模式还通过限制对共享数据的直接访问来加强数据完整性。...中进行数据的请求,而不是在componentWillMount;需要根据 props 更新 state 时,使用getDerivedStateFromProps(nextProps, prevState

    1.3K10
    领券