首页 > 解决方案 > 如何一个一个地同时加载和渲染数据

问题描述

我想找到一种方法来用按下按钮加载的数据填充表格。通过处理一堆文件来加载数据。每项数据的加载大约需要四分之一秒。

目前,我正在为整个页面使用功能组件并为状态使用挂钩。我想一个一个地加载和渲染数据,但是当我(用户)开始加载时,应用程序冻结了,我无法点击甚至删除应用程序。但是,加载后,应用程序会使用收集的数据恢复。

我尝试了几种不同的解决方案,我将详细说明每种解决方案失败的原因。

悬念或延迟加载: 想法是在准备好后立即加载下一个项目。这些解决方案要求所有数据在全部加载后同时呈现。我正在寻找一种在加载每个项目时一次渲染它们的方法。

Generators/Callbacks: 当点击按钮并开始加载数据的功能时,应用程序会冻结,直到所有数据都加载完毕。

承诺: 我可能用错了。我的印象是每个项目都需要单独的承诺。然后,我将不得不使用上述解决方案之一。

React useEffect: 不确定这如何帮助状态更新和每次回调重新渲染。

export function loadTheData(callback) {
  for (const file of getFiles()) {
    callback(file);
  }
}

getFiles 是一个生成器函数。

import React, { useState, useReducer, useCallback, useEffect } from 'react';
import { Button } from '@blueprintjs/core';
import { loadTheData} from '../../actions/data';
import Page from '../common/Page';

export default function MyComp() {

  const [data, setData] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  function loadData() {
    if (isLoading) {
      return;
    }
    setIsLoading(true);

    loadTheData(item => { // loadTheData is an external function
      setData(prevData => [...prevData, item]);
    });
    setIsLoading(false);
  }

  return (
    <Page>
      <Button
        onClick={loadData}
        loading={isLoading}
      />
      <p>{data.length}</p>
    </Page>
  );
}

I expect the data.length value to increase one by one until it's complete after I press the button, but instead it is frozen at 0 until the end when it changes to the correct data length. The loadTheData function provides the data one at a time into the callback function. I know the loadTheData function and other parts of the code work properly. I'm just not sure how to go about concurrently/asynchronously loading and rendering the data that is loaded.

标签: javascriptreactjscallbackelectronreact-hooks

解决方案


Your loadTheData function should look like this

function loadTheData(cb) {
   return Promise.all(getFiles().map(file => api.call().then(cb)))
}

Then use it in the component like this

  async function loadData() {
    if (isLoading) {
      return;
    }
    setIsLoading(true);

    await loadTheData(item => { // loadTheData is an external function
      setData(prevData => [...prevData, item]);
    });
    setIsLoading(false);
  }


推荐阅读