当前位置: 首页 > 知识库问答 >
问题:

javascript - React中使用requestIdleCallback优化大量数据渲染?

严项明
2024-04-07

如何在react中使用requestIdleCallback来实现大量数据的渲染优化?

image.png
目前通过这种方式处理之后最后一组数据屏幕一直闪烁,请教一下大佬们。
这里只是测试的数据,之所以没采用虚拟列表是因为真实数据中的每一项的高度不固定,虚拟列表处理起高度计算有点复杂。

共有2个答案

隆飞宇
2024-04-07
const usePerformTask = <T>(data: T[], run: (batch: T[]) => void, batchSize = 10) => {  const dataRef = useRef(data);  useEffect(() => {    dataRef.current = data;  }, [data]);  useEffect(() => {    let isCancelled = false;    const performTask = (deadline: IdleDeadline) => {      while (!isCancelled && dataRef.current.length > 0 && deadline.timeRemaining() > 0) {        const batch = dataRef.current.splice(0, batchSize);        run(batch);      }      if (!isCancelled && dataRef.current.length > 0) {        requestIdleCallback(performTask);      }    };    requestIdleCallback(performTask);    return () => {      isCancelled = true;    };  }, [batchSize]);};

简单的自定义一个hooks来解决这个问题。
大量数据分片渲染,可以使用deadline.timeRemaining这个方法来判断当前帧是否还有时间做任务。

拓拔富
2024-04-07

React 中使用 requestIdleCallback 可以帮助优化大量数据的渲染,特别是在浏览器空闲时执行高优先级的渲染任务。requestIdleCallback 是一个浏览器提供的 API,它允许你在主线程空闲时执行后台或低优先级的任务。

要在 React 中使用 requestIdleCallback 来优化大量数据的渲染,你可以按照以下步骤进行:

  1. 创建一个处理函数:这个函数将负责渲染你的数据。它应该接受一个 deadline 对象作为参数,这个对象包含了一个 timeRemaining 方法,可以用来检查还剩下多少可用的空闲时间。
function handleIdle(deadline) {  const startTime = performance.now();  // 渲染数据的逻辑  renderData();  const usedTime = performance.now() - startTime;  // 如果还有剩余时间,请求下一个空闲回调  if (deadline.timeRemaining() > usedTime) {    requestIdleCallback(handleIdle);  }}
  1. 在组件中调用 requestIdleCallback:在你的 React 组件中,当需要渲染大量数据时,调用 requestIdleCallback 并传入你的处理函数。
class MyComponent extends React.Component {  componentDidMount() {    if ('requestIdleCallback' in window) {      window.requestIdleCallback(this.handleIdle);    }  }  handleIdle = (deadline) => {    // 渲染数据的逻辑    this.renderData();    const usedTime = performance.now() - deadline.timeRemaining();    // 如果还有剩余时间,请求下一个空闲回调    if (deadline.timeRemaining() > usedTime) {      window.requestIdleCallback(this.handleIdle);    }  };  renderData() {    // 渲染你的数据  }  render() {    // 渲染你的组件  }}
  1. 处理数据渲染:在 renderData 函数中,根据你的数据渲染组件。你可能需要分批处理数据,以便在浏览器空闲时逐步渲染。
renderData() {  // 假设 this.props.data 是你要渲染的数据  const batchSize = 100; // 你可以根据需要调整这个值  for (let i = 0; i < this.props.data.length; i += batchSize) {    const end = Math.min(i + batchSize, this.props.data.length);    this.setState({ renderedData: this.props.data.slice(i, end) });  }}
  1. 处理组件卸载:在组件卸载时,确保取消任何待处理的 requestIdleCallback
componentWillUnmount() {  if ('cancelIdleCallback' in window) {    window.cancelIdleCallback(this.handleIdle);  }}

关于你提到的屏幕闪烁问题,这可能是由于数据渲染时引起的重渲染。你可以尝试以下方法来解决:

  • 使用 shouldComponentUpdateReact.memo:通过阻止不必要的重渲染来优化性能。
  • 使用 CSS 动画或过渡:如果闪烁是由于元素突然出现在屏幕上,考虑使用 CSS 动画或过渡来平滑地显示元素。
  • 优化渲染逻辑:确保你的渲染逻辑尽可能高效,避免在每次渲染时执行昂贵的操作。

由于你没有提供具体的代码和屏幕闪烁的具体细节,以上建议可能需要根据你的实际情况进行调整。

 类似资料:
  • 本文向大家介绍使用vue渲染大量数据时应该怎么优化?说下你的思路!相关面试题,主要包含被问及使用vue渲染大量数据时应该怎么优化?说下你的思路!时的应答技巧和注意事项,需要的朋友参考一下 虚拟列表:vue-virtual-scroll-list,vue-virtual-scroller…… 冻结属性,让不必要的属性不响应:, 或者使用 将对象属性的设置为,源码:vue/src/core/obser

  • 我在mysql中有这些数据。 我想调整数据并将其发送到json使用节点js / expressjs与每日,每月,每年的总和。 首先我尝试这个查询。 这个查询运行良好。但我认为这是浪费。因为反复查询代码数量。 输出: 我可以用一个查询获取所有数据吗? 最后,我想用Expresjs发送这种形式的数据。 或此表单 我尝试过mysql查询,sequelize,洛达什。但我找不到正确的方法。

  • 问题内容: 我需要通过REST API的Batch端点将大量节点及其之间的关系插入到Neo4j中,大约每秒5k记录(仍在增加)。 这将是24x7连续插入。每条记录可能只需要创建一个节点,而其他记录可能需要两个节点并创建一个关系。 是否可以通过更改程序或修改Neo4j的设置来提高插入件的性能? 到目前为止,我的进度: 1.我已经使用Neo4j进行了一段时间的测试,但无法获得所需的性能 测试服务器盒:

  • 问题内容: 我以TodoList为例来反映我的问题,但是显然我的实际代码更加复杂。 我有一些这样的伪代码。 我所有的数据都是不可变的,并且使用了并且一切正常。修改待办事项数据后,仅 重新渲染父项和已编辑的待办事项。 问题是,随着用户的滚动,我的列表有时会变得很大。并且,当更新单个待办事项时,渲染 父项,调用shouldComponentUpdate所有待办事项以及渲染单个待办事项所花费的时间越来越

  • 优化提升渲染性能,不仅能让页面更快的展现、可交互,同时能提升用户操作滚动的流畅度,对提升用户体验至关重要。 避免不必要的更新对比 Rax 同 React 一样,render 时会有 vdom 对比,如果对比发现 DOM 没有变化时,不会去真正更新页面。而本身 vdom 对比也是不小的消耗,你应该避免这种不必要的更新对比,使用 shouldComponentUpdate 方法明确标识你的组件什么时候

  • 今天和同事偶然讨论起了这个问题。虽然现在公司 vue3 是主力,但是之前曾了解过 react setState 是做了合并渲染的优化的。类似于: 在 react 中是不会一行一行代码同步执行更新 dom 的,而是会在某个时间点合并相同的修改,只执行一次渲染。 那么 vue 中有没有类似的优化呢?如果有那么是哪里用到了呢?