Предотвратить сброс позиции прокрутки реагирующей точки пути вверх после извлечения и добавления элементов

У меня есть компонент, структурированный, как показано ниже. Он использует react-waypoint для извлечения и рендеринга дополнительных карточек, как только пользователь достигает конца коллекции карточек.

componentDidMount() {
    const { actions, user } = this.props;
    if (!user) return;
    actions.getConnections(user.guid, 0, DEFAULT_FETCH_ROW_COUNT)
        .then(({ data }) => {
            this.setState({
                fullyLoaded: data.length < DEFAULT_FETCH_ROW_COUNT,
                firstLoaded: true
            });
        });
}

loadMoreConnections(rows = DEFAULT_FETCH_ROW_COUNT) {
    const { user, connections, actions } = this.props;
    const { fullyLoaded } = this.state;

    if (fullyLoaded) return;
    return actions.getConnections(user.guid, connections.length, rows, true)
        .then(({ data }) => {
            this.setState({
                fullyLoaded: data.length < rows
            });
        });
}

showConnections() {
    const { user, connections, actions } = this.props;
    return (
        connections.map((connection, index) => (
            <div className="col-12 col-md-6 col-lg-4 col-xl-3 card-wrapper" key={index}>
                {(!this.state.fullyLoaded && index === (connections.length - THRESHOLD)) && (index >= DEFAULT_FETCH_ROW_COUNT - THRESHOLD) && (
                    <Waypoint
                        onEnter={() => {
                            this.loadMoreConnections();
                        }}
                    />
                )}
                <Link
                    id={`${idPrefix}ConnectionCardLink${index}`}
                    to={`/${ROUTES.PROFILE}/${getProfileUrl(connection)}`}
                >
                    <ConnectionCard
                        idPrefix={idPrefix}
                        src={connection.photo ? connection.photo.url : ''}
                        idSuffix={index}
                    >
                        <h5 id={`${idPrefix}NameTxt${index}`}
                            className="text-truncate font-weight-bold">{connection.firstname} {connection.lastname}</h5>
                        <h6 id={`${idPrefix}PrimaryJobTxt${index}`}
                            className="text-truncate text-secondary primary-job">
                            {connection.primaryWorkHistory
                                ? (
                                    `${connection.primaryWorkHistory.jobs[0].jobName} @ ${connection.primaryWorkHistory.employer.name}`
                                    + `${connection.primaryWorkHistory.employer.location
                                        ? `, ${connection.primaryWorkHistory.employer.location.city}, ${connection.primaryWorkHistory.employer.location.state}`
                                        : '' }`
                                )
                                : ' '
                            }
                        </h6>
                        <div className="button-group">
                            <Link
                                id={`${idPrefix}ViewProfileBtn${index}`}
                                className="button hollow small"
                                to={`/${ROUTES.PROFILE}/${getProfileUrl(connection)}`}
                            >
                                View Profile
                            </Link>
                            <Button
                                id={`${idPrefix}MessageBtn${index}`}
                                className="small"
                                label="Message"
                                onClick={(e) => {
                                    e.preventDefault();
                                    actions.openChatByParticipants(user, connection);
                                }}
                            />
                        </div>
                    </ConnectionCard>
                </Link>
            </div>
        ))
    );
}

showNoResults() {
    return (
        <EmptySearchResults
            idPrefix={`${idPrefix}EmptySearch`}
            title="Don’t be shy."
            description="It looks like you don’t have any connections, but don’t worry you can search our community."
        >
            <Link
                id={`${idPrefix}GetConnectedBtn`}
                className="button action-button"
                to={`/${ROUTES.COMMUNITY}/suggested`}
            >
                Get Connected
            </Link>
        </EmptySearchResults>
    )
}

render() {
    const { connections, isFetchingConnections } = this.props;
    const { firstLoaded } = this.state;
    let view = null;

    if (connections.length) {
        view = this.showConnections();
    } else if (firstLoaded) {
        view = this.showNoResults();
    }

    return (
        <div className="row">
            {view}
        </div>
    );
}

Это работает, как и ожидалось, но я хочу отображать компонент загрузчика, пока эти дополнительные данные извлекаются и отображаются. Для этого я попытался реализовать компонент загрузчика, добавив/изменив следующее:

showLoader() {
    return (
        <div className="select-overlay-loader d-flex justify-content-center align-items-center">
            <Loader />
        </div>
    );
}

if(isFetchingConnections) {
        view = this.showLoader();
    } else if (connections.length) {
        view = this.showConnections();
    } else if (firstLoaded) {
        view = this.showNoResults();
    }

Эти изменения действительно отображают компонент загрузчика, пока извлекаются и отображаются дополнительные данные карты, но после того, как новые карты добавлены в список, прокрутка списка сбрасывается наверх. Я не уверен, как я могу сохранить местоположение прокрутки списка между выборками.

Я видел ответы на подобные вопросы, такие как этот one

которые предлагают установить список scrollTop в текущий список scrollHeght перед получением новых данных.

Я пытался, но не смог реализовать это исправление.

Проблема в том, где находится компонент? Я видел примеры, когда элемент помещается в конец отображаемого списка, но в этом случае компонент включается в начало каждого компонента карты в функции карты.

Я работаю над существующей кодовой базой и новичок в React, поэтому, пожалуйста, простите мою невежественность. Я надеюсь, что мой вопрос представлен ясно.

Может кто-то указать мне верное направление?

Ваше здоровье!


person Randall Spencer    schedule 20.08.2017    source источник


Ответы (1)


Чтобы реализовать обратную бесконечную прокрутку в React.js, вам нужно сделать что-то вроде этого:

componentWillUpdate() {
    this.scrollHeight = this.scrollableElement.scrollHeight;
    this.scrollTop = this.scrollableElement.scrollTop;
}

componentDidUpdate() {
    this.scrollableElement.scrollTop = this.scrollTop +
        (this.scrollableElement.scrollHeight - this.scrollHeight);
}

Перед каждым обновлением вы сохраняете последнюю позицию прокрутки, а после обновления просто восстанавливаете ее. Это сработало для меня. В моем случае компонент путевой точки размещен вверху.

Я нашел это решение здесь: http://blog.vjeux.com/2013/javascript/scroll-position-with-react.html.

person veob    schedule 01.02.2018