React/reselect 如何在重新计算选择器之前刷新 ui
React/reselect how to refresh ui before a selector is recomputed
在我的 React-App (create-react-app) 中,我使用一个选择器(使用 reselect 创建)从存储的数据中计算派生数据。
问题是,选择器需要很长时间才能计算。我想在用户界面上显示微调器(或消息)。但是每次重新计算选择器时,ui 都会冻结。
我读了很多东西(Web Worker、requestIdleCallback、requestAnimationFrame)并尝试制作我自己的 React 钩子,但我被卡住了。我无法在回调中使用选择器。
搜索结果只是为了在重新计算选择器之前刷新ui。
这就是我的解决方案。我不知道它是否是 "good" 或者它是否违反了一些反应或重新选择的规则,但它有效。也许您可以评估一下?
代码已简化以提高可读性。
想法是,选择器 returns 一个 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;
在我的 React-App (create-react-app) 中,我使用一个选择器(使用 reselect 创建)从存储的数据中计算派生数据。
问题是,选择器需要很长时间才能计算。我想在用户界面上显示微调器(或消息)。但是每次重新计算选择器时,ui 都会冻结。
我读了很多东西(Web Worker、requestIdleCallback、requestAnimationFrame)并尝试制作我自己的 React 钩子,但我被卡住了。我无法在回调中使用选择器。
搜索结果只是为了在重新计算选择器之前刷新ui。
这就是我的解决方案。我不知道它是否是 "good" 或者它是否违反了一些反应或重新选择的规则,但它有效。也许您可以评估一下?
代码已简化以提高可读性。
想法是,选择器 returns 一个 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;