显示 img 行时反应表加载缓慢

iva*_*txo 4 javascript html-table loadimage reactjs

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

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

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

谢谢大家。

更新 有人建议我使用同步/等待功能来加载图像。然后我正在更新代码。但是,我的主要问题仍然是:加载数据,特别是徽标列。所有数据都被渲染,但不是标志列,然后每个标志开始一个一个地渲染,看起来很慢。我认为该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')
    );
Run Code Online (Sandbox Code Playgroud)

Gal*_*bra 7

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

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

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

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