【问题标题】:Implement custom infinite scrolling in react在反应中实现自定义无限滚动
【发布时间】:2020-12-04 05:16:11
【问题描述】:

我试图实现无限滚动,但是当组件重新渲染时,滚动条会一直回到顶部,如下所示。如何将滚动条粘贴到用户滚动的位置?还是因为组件重新渲染?但是组件必须重新渲染,因为新记录是从 api 调用中添加的。

AppList.tsx

  //Initial values
  const [pageNumber, setPageNumber] = useState<number>(1);
  const [scrolling, setScrolling] = useState<boolean>(false);
  const [totalPages, setTotalPages] = useState<number>(3);

<div ref={divRef} className={AppList.Container} onScroll={() => {
        if (scrolling && totalPages! <= pageNumber!) {
          return;
        }
        else {
          const nodes = document.querySelectorAll('.ms-List-cell');
          const lastLi: Element = nodes[nodes.length - 1];
          const lastLiOffset = lastLi.getBoundingClientRect().top + lastLi.clientHeight;
          const pageOffset = window.pageYOffset + window.innerHeight;
          var bottomOffset = 150;
          if (pageOffset > lastLiOffset - bottomOffset) {
            setScrolling!(true);
            setPageNumber!(pageNumber! + 1);
            dispatch(GetAllAppDefinitions(dispatch, pageNumber! + 1));(Service call)
          }
        }
      }}>
        {updatedColumns.length > 0 && (
          <DetailsList
            className={appListTableStyle}
            columns={updatedColumns}
            selectionMode={SelectionMode.none}
            items={updatedItems || []}
          />
        )}
      </div>

【问题讨论】:

    标签: reactjs scroll infinite-scroll rerender


    【解决方案1】:

    这是一个使用 React Hooks 无限滚动的基本示例,您可以根据需要对其进行修改以发出 API 请求并将其推送到您的数据中,

    import React, { useEffect, useState, useRef  } from 'react';
    
    const divStyle = {
        color: 'blue',
        height: '250px',
        textAlign: 'center',
        padding: '5px 10px',
        background: '#eee',
        marginTop: '15px'
    };
    
    
    const containerStyle = {
        maxWidth: '1280px',
        margin: '0 auto',
    }
    const InfiniteScroll = () => {
        const [postList, setPostList] = useState({
            list: [1,2,3,4]
        }); 
        // tracking on which page we currently are
        const [page, setPage] = useState(1);
        // add loader refrence 
        const loader = useRef(null);
    
        useEffect(() => {
             var options = {
                root: null,
                rootMargin: "20px",
                threshold: 1.0
             };
            // initialize IntersectionObserver
            // and attaching to Load More div
             const observer = new IntersectionObserver(handleObserver, options);
             if (loader.current) {
                observer.observe(loader.current)
             }
    
        }, []);
    
    
        useEffect(() => {
            // here we simulate adding new posts to List
            const newList = postList.list.concat([1,1,1,1]);
            setPostList({
                list: newList
            })
        }, [page])
    
        // here we handle what happens when user scrolls to Load More div
       // in this case we just update page variable
        const handleObserver = (entities) => {
            const target = entities[0];
            if (target.isIntersecting) {   
                setPage((page) => page + 1)
            }
        }
    
    
        return (<div className="container" style={containerStyle}>
            <div className="post-list">
                {
                    postList.list.map((post, index) => {
                        return (<div key={index} className="post" style={divStyle}>
                            <h2> {post } </h2>
                        </div>)
                    })
                }
                 <!-- Add Ref to Load More div -->
                <div className="loading" ref={loader}>
                        <h2>Load More</h2>
               </div>
            </div>
        </div>)
    }
    
    export default InfiniteScroll;
    

    致谢 => https://dev.to/hunterjsbit/react-infinite-scroll-in-few-lines-588f

    【讨论】:

    • 但在我的情况下,“加载更多”div 将不起作用,因为它是一个行表,并且 api 正在从 api 加载新行。我应该如何引用表中的最后一个孩子?
    • 如果您可以发布您的代码,它可以帮助您了解如何使用无限滚动进行锻炼。并且可以让它工作
    • 刚刚更新了代码。问题在于呈现滚动条并需要处理该滚动条的“DetailsList”组件。
    【解决方案2】:

    这就是我实现无限滚动的方式。如果您在内部元素而不是窗口上滚动,则 scrollElement 正在设置

    import React from 'react';
    import PropTypes from 'prop-types';
    
    componentDidMount() {
      const {
        initialLoad,
        initialPage,
        loadMore,
        scrollElement
      } = this.props;
        (scrollElement || window).addEventListener('scroll', this.handleScroll);
        if (initialLoad) {
          loadMore(initialPage);
        }
      }
    
      componentWillUnmount() {
        const { scrollElement } = this.props;
        (scrollElement || window).removeEventListener('scroll', this.handleScroll);
      }
    
      handleScroll = () => {
        const {
          loadMore, threshold, hasMore, loading, page, scrollElement
        } = this.props;
        if (scrollElement) {
          const contentHeight = document.getElementById('scroller').clientHeight;
          const {  scrollTop } = scrollElement;
          const { y, height } = scrollElement.getBoundingClientRect();
          if (((height - y) + scrollTop) > contentHeight - threshold && hasMore && !loading) {
            loadMore(page);
          }
          return;
        }
        const { innerHeight, scrollY } = window;
        const contentHeight = document.getElementById('scroller').clientHeight;
        if (innerHeight + scrollY > contentHeight - threshold && hasMore && !loading) {
          loadMore(page);
        }
      };
    
      render() {
        const {
          loading, children, loader, className
        } = this.props;
        return (
          <div
            id="scroller"
            className={ className }
          >
            { children }
            { loading ? loader : null }
          </div>
        );
      }
    

    }

    【讨论】:

      【解决方案3】:

      你可以检查我的实现on this medium article你根本不需要使用onScroll!

      我的猜测是,如果您将 bar 移到顶部,则可能您正在安装/卸载列出项目的组件。您需要做的只是逐步加载项目。如果列出项目的组件保持安装状态,则不应发生滚动:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多