在重新计算选择器之前做出反应/重新选择如何刷新ui

时间:2020-03-19 07:03:18

标签: reactjs redux reselect

在我的React-App(create-react-app)中,我使用一个选择器(通过reselect创建)来从存储的数据计算派生数据。
问题是,选择器需要很长时间才能计算出来。我想在用户界面上显示微调框(或消息)。但是每次重新选择选择器时,UI都会冻结。

我读了很多东西(Web Worker,requestIdleCallback,requestAnimationFrame)并尝试制作自己的React钩子,但是我被卡住了。我无法在回调中使用选择器。

搜索结果只是在重新计算选择器之前刷新ui。

1 个答案:

答案 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;