我的代码看起来像这样:
// 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,但它不能与异步一起工作。
发布于 2020-07-12 15:26:31
您可以对fetchData进行分组,当使用相同的参数调用fetchData时,将检查缓存中的promise,并返回promise,而不是创建一个新的promise(创建一个新的fetch)。
当promise解析时,该缓存项将被删除,因此当组件再次挂载时,它将再次获取。要改变这种行为,你可以向group函数传递一个不同的缓存对象。
//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)
);
发布于 2021-05-05 00:49:13
我认为你应该能够这样做,目标是将调用缓存一段时间,然后将它们一次性传递给unstable_batchedUpdates。
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。
https://stackoverflow.com/questions/62857109
复制相似问题