【问题标题】:React table slow loading when displaying img rows显示 img 行时反应表加载缓慢
【发布时间】:2020-07-24 22:33:10
【问题描述】:

我是 React 新手。我只是想构建一个来自我获取的 API 的数据表。但现在我想将数据呈现到表格中。

我的问题是其中一列是来自 URL index.php?Action=GetLogo&id=51 的徽标。结果数量超过 300。即使我已经在使用分页,表格渲染速度也很慢,尤其是 logo 列。所有数据都已加载,但我可以看到每个徽标都在逐行呈现,给用户带来了缓慢的体验。

React 有什么方法可以解决这个问题吗?有人请指出我正确的方向如何解决这个问题。

谢谢大家。

更新 有人建议我使用同步/等待功能来加载图像。然后我正在更新代码。但是我的主要问题仍然存在:加载数据,尤其是徽标列。所有的数据都被渲染了,但不是 logo 列,然后每个 logo 开始一个接一个地渲染,看起来很慢。我认为async/await 函数会缓解这种情况。

    import React from 'react';
    import ReactDOM from 'react-dom';
    import FormData from 'form-data';

    class FilterableSupplierTable extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                suppliers: []
            }
        }

        componentDidMount() {
            let formData = new FormData();
            formData.append('AjaxMethodName', 'GetSuppliers');
            const options = {
                method: 'POST',
                headers: {
                    'Accept': '*/*'
                },
                body: formData
            };
            fetch(`?Model=route_to_controller`, options)
                .then(response => response.json())
                .then(data => {
                    this.setState({ suppliers: JSON.parse(data.response_data) })
                });
        }

        async getLogos(suppliers) {
            return await Promise.all(
                suppliers.map(async supplier => {
                    supplier.new_logo = !!supplier.has_logo ?
                        <img style={{maxWidth: "100px"}} src={supplier.logo} alt={supplier.supplier_id} /> :
                        <i className="icon icon-warning no_logo">&nbsp;No Logo</i>;
                    return supplier;
                });
            );
        }

        render() {
            const rows = [];
            const suppliers = this.state.suppliers;
            this.getLogos(suppliers)
                .then(results => {
                    results.map(supplier => {
                        rows.push(
                            <tr>
                                {/* supplier.logo is index.php?Action=GetLogo&id=51, etc */}
                                <td><img src={supplier.new_logo} /></td>
                                <td>{supplier.name}</td>
                            </tr>
                        );
                    });
                });

            return (
                <table>
                    <thead>
                        <tr>
                            <th colSpan="4">Suppliers</th>
                        </tr>
                        <tr>
                            <th>Logo</th>
                            <th>Name</th>
                        </tr>
                    </thead>
                    <tbody>{rows}</tbody>
                </table>
            );
        }
    }
    ReactDOM.render(
        <FilterableSupplierTable />,
        document.getElementById('suppliers_list')
    );

【问题讨论】:

  • 有时图像的大小会增加开发环境中的加载时间你确定图像是网络优化的吗?
  • “滞后”可能意味着更多。尝试使用awaitSuspense
  • @AdrianPascu 我会检查一下谢谢我也更新了标题。
  • 会不会是这些图像非常“沉重”的情况?高分辨率且未优化会导致在表格组件中呈现大文件?
  • @AdrianPascu。你能给我举个例子,我该如何使用这些块吗?

标签: javascript reactjs html-table loadimage


【解决方案1】:

我认为您的问题已解决。但是,除此之外,我建议您查看 React Virtualized,https://github.com/bvaughn/react-virtualized

希望有一天这会有所帮助。

【讨论】:

    【解决方案2】:

    您的问题可以通过更新“全局加载状态”的组件来解决。

    只有在 所有 图像更新完成加载后,它们才会一起可见:

    function MyImage(props) {
      const onLoad = () => {
        props.onLoad();
      };
    
      return (
        <div>
          {props.isCurrentlyLoading && <div>Loading</div>}
          <img
            src={props.src}
            onLoad={onLoad}
            style={
              props.isCurrentlyLoading
                ? { width: "0", height: "0" } // You can also use opacity, etc.
                : { width: 100, height: 100 }
            }
          />
        </div>
      );
    }
    
    function ImagesBatch() {
      const [loadedImagesCounter, setLoadedImagesCounter] = useState(0);
      const [isAllLoaded, setIsAllLoaded] = useState(false);
    
      const updateLoading = () => {
        if (loadedImagesCounter + 1 === imagesUrls.length) {
          setIsAllLoaded(true);
        }
        setLoadedImagesCounter(prev => prev + 1);
      };
    
      return (
        <div>
          {imagesUrls.map((url, index) => {
            return (
              <MyImage
                key={url}
                src={url}
                index={index + 1}
                isCurrentlyLoading={!isAllLoaded}
                onLoad={updateLoading}
              />
            );
          })}
        </div>
      );
    }
    

    您可以查看完整代码 here(最好使用开放式控制台),其中我使用了任意 ~6MB 图像作为示例。

    【讨论】:

    • 我正在检查谢谢。如果我使用你的,我什至不需要我的 getLogos (async/await) 函数?我的图片在 KB 上:p
    • @ivantxo 没错。您只需要过滤您的客户数组,以确保您只计算那些具有有效图片网址的人
    • 我怎样才能为所有元素使用一条Loading 消息,而不是为每张图像使用一条Loading 消息?
    • 是的,只需将其从MyImage 中删除并添加到ImagesBatch
    • 我在进入 React 方面还有很长的路要走......谢谢@GalAbra
    猜你喜欢
    • 2016-05-17
    • 1970-01-01
    • 2022-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-11
    • 2022-08-03
    • 2021-11-30
    相关资源
    最近更新 更多