在获取和追加项目后,防止反应 - 航点滚动位置从重置到顶部

时间:2017-08-20 02:21:14

标签: javascript reactjs scrollview lazy-loading jquery-waypoints

我的组件结构如下。一旦用户到达卡片集的末尾,它就会使用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。

我已尝试过,但未能实施此修复程序。

组件放置的问题是什么?我已经看到了放置在渲染列表末尾的示例,但在这种情况下,组件包含在map函数中每个卡组件的顶部。

我正在研究现有的代码库并且是React的新手,所以请原谅我的任何无知。我希望我的问题能够清楚地呈现出来。

有人能指出我正确的方向吗?

干杯!

1 个答案:

答案 0 :(得分: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