首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >跨微任务批处理React更新?

跨微任务批处理React更新?
EN

Stack Overflow用户
提问于 2020-07-12 12:33:54
回答 2查看 298关注 0票数 6

我的代码看起来像这样:

代码语言:javascript
复制
// File1
async function fetchData() {
  const data = await fetch(...);
  setState({ data });
  return data;
}

// File2
useEffect(() => {
  (async () => {
    const data = await fetchData();
    setState({ data });
  })();
});

这会在1个任务中触发2个React提交。这使得我的应用程序低于60FPS。理想情况下,我希望批处理这两个setState。目前,它看起来是这样的:

粉色表示React提交(DOM操作)。直到第二次提交完成,浏览器才有机会重新绘制。我可以通过在setStates之间添加await new Promise(succ => setTimeout(succ, 0));来给浏览器一个重绘的机会,但是如果我可以批量提交就更好了。

这也几乎不可能重构,因为useState存在于不同的文件中。

我尝试过unstable_batchedUpdates,但它不能与异步一起工作。

EN

回答 2

Stack Overflow用户

发布于 2020-07-12 15:26:31

您可以对fetchData进行分组,当使用相同的参数调用fetchData时,将检查缓存中的promise,并返回promise,而不是创建一个新的promise(创建一个新的fetch)。

当promise解析时,该缓存项将被删除,因此当组件再次挂载时,它将再次获取。要改变这种行为,你可以向group函数传递一个不同的缓存对象。

代码语言:javascript
复制
//group function (will always return promise)
const createGroup = (cache) => (
  fn,
  getKey = (...x) => JSON.stringify(x)
) => (...args) => {
  const key = getKey(args);
  let result = cache.get(key);
  if (result) {
    return result;
  }
  //no cache
  result = Promise.resolve(fn.apply(null, args)).then(
    (r) => {
      cache.resolved(key); //tell cache promise is done
      return r;
    },
    (e) => {
      cache.resolve(key); //tell cache promise is done
      return Promise.reject(e);
    }
  );
  cache.set(key, result);
  return result;
};
//cache that removes cache entry after resolve
const createCache = (cache = new Map()) => {
  return {
    get: (key) => cache.get(key),
    set: (key, value) => cache.set(key, value),
    //remove cache key when resolved
    resolved: (key) => cache.delete(key),
    //to keep cache:
    //resolved: () => 'NO_OP',
  };
};

//fetch data function
const fetchData = (...args) => {
  console.log('fetch data called with', args);
  return new Promise((resolve) =>
    setTimeout(() => resolve(args), 1000)
  );
};
//grouped fetch data
const groupedFetchData = createGroup(createCache())(
  fetchData
);
groupedFetchData(1, 2, 3).then((resolve) =>
  console.log('resolved with:', resolve)
);
groupedFetchData(1, 2, 3).then((resolve) =>
  console.log('resolved with:', resolve)
);

票数 0
EN

Stack Overflow用户

发布于 2021-05-05 00:49:13

我认为你应该能够这样做,目标是将调用缓存一段时间,然后将它们一次性传递给unstable_batchedUpdates

代码语言:javascript
复制
import { unstable_batchedUpdates } from 'reactDOM'
import raf from 'raf'

const cache = []
let rafId = null

function setBatchedState(setState, data) {
  cache.push({ setState, data })

  if(!rafId) {
    rafId = raf(() => {
      unstable_batchedUpdates(() => {
        cache.forEach(({setState, data}) => setState(data))
      })

      rafId = null
      cache = []
    })
  }
}

export default setBatchedState

这是使用requestAnimationFrame来解除对unstable_batchedUpdates的调用,根据您的用例,您可能更喜欢使用setTimeout

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62857109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档