Реагировать на медленную загрузку таблицы при отображении строк img - PullRequest
4 голосов
/ 12 апреля 2020

Я новичок в React. Я просто пытаюсь создать таблицу данных, поступающих из API, который я получил из него. Но теперь я хочу сделать данные в виде таблицы.

Моя проблема в том, что одним из столбцов является lo go, который приходит с URL index.php?Action=GetLogo&id=51. Количество результатов превышает 300. Несмотря на то, что я уже использую нумерацию страниц, рендеринг таблицы идет медленно, особенно столбец logo. Все данные загружаются, но я вижу, что каждый lo go выводится строка за строкой, давая пользователю медленный опыт.

Есть ли какой-нибудь способ, которым React может подойти для решения этой проблемы? Кто-то, пожалуйста, укажите мне правильное направление, как справиться с этим.

Спасибо всем.

Обновление Кто-то посоветовал мне использовать функцию синхронизации / ожидания для загрузки изображений , Затем я обновляю код. Тем не менее, моя главная проблема по-прежнему со мной: загрузка данных, в частности столбца lo go. Отрисовываются все данные, кроме столбца lo go, тогда каждый lo go начинает отображаться один за другим, выглядя очень медленно. Я думал, что функция 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')
    );

Ответы [ 2 ]

7 голосов
/ 19 апреля 2020

Ваша проблема может быть решена с помощью компонента, который обновляет «глобальное состояние загрузки».

Только после того, как все изображения обновятся после завершения загрузки, они становятся видимыми вместе:

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>
  );
}

Вы можете проверить полный код здесь (желательно с открытой консолью), где в качестве примера я использовал произвольное изображение размером ~ 6 МБ.

1 голос
/ 25 апреля 2020

Я думаю, вы решили свои проблемы. Но, кроме этого, я предлагаю вам оформить заказ React Virtualized, https://github.com/bvaughn/react-virtualized

Надеюсь, это когда-нибудь поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...