在我的React-App(create-react-app)中,我使用一个选择器(通过reselect创建)来从存储的数据计算派生数据。
问题是,选择器需要很长时间才能计算出来。我想在用户界面上显示微调框(或消息)。但是每次重新选择选择器时,UI都会冻结。
我读了很多东西(Web Worker,requestIdleCallback,requestAnimationFrame)并尝试制作自己的React钩子,但是我被卡住了。我无法在回调中使用选择器。
搜索结果只是在重新计算选择器之前刷新ui。
答案 0 :(得分:0)
那是我的解决方案。我不知道它是否“好”,或者是否违反了一些反应或重新选择的规则,但是它可以工作。也许您可以评估一下?
简化代码以提高可读性。
这个想法是,选择器返回一个Promise,我在计算数据之前调用requestAnimationFrame
,以获得刷新ui的机会。
selector.js:
const dataSelector = state => state.data;
export const getDataComputedPromise = createSelector([dataSelector], (data) => {
const compute = function () {
return new Promise((resolve) => {
// heavy computing stuff
resolve(computedData);
});
};
return new Promise((resolve) => {
let start = null;
let requestId = null;
function step (timestamp) {
if (!start) {
start = timestamp;
window.cancelAnimationFrame(requestId);
requestId = window.requestAnimationFrame(step);
return;
};
compute().then(freeResources => {
window.cancelAnimationFrame(requestId);
resolve(freeResources);
});
}
requestId = window.requestAnimationFrame(step);
});
});
myPage.js
const MyPage = ({ someProps }) => {
...
const dataComputedPromise = useSelector(getDataComputedPromise);
const [dataComputed, setDataComputed] = useState([]);
const [computeSelector, setComputeSelector] = useState(false);
useEffect(() => {
setComputeSelector(true);
}, [data]);
useEffect(() => {
dataComputedPromise.then(dataComputed => {
setDataComputed(dataComputed);
setComputeSelector(false);
});
}, [dataComputedPromise]);
...
return <div>
<Loader active={compueSelector}>Computing data...</Loader>
</div>;
};
export default MyPage;