css 在React中加载更多数据(无限滚动)时,如何避免滚动条停留在顶部

kadbb459  于 2022-11-19  发布在  React
关注(0)|答案(2)|浏览(343)

我在聊天室无限向上滚动,判断看到最后一条消息并加载数据,但滚动条仍然停留在页面顶部,你知道,它会自动无限执行调用api,如何保持滚动条在上一条消息的位置

cotxawn7

cotxawn71#

如果您有所加入新元素的指涉,可以使用element.scrollIntoView()来确定呈现后它是可见的。
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
但是:在聊天室里,这可能并不总是正确的做法,因为用户可能会向上滚动来复制/粘贴一些东西,而丢失位置会很烦人。所以在通过JS滚动之前,请检查聊天是否已经在底部。
你可以看看twitch-chat是如何工作的,以获得一个很好的例子。如果有新的聊天消息,用户会得到一个信息。

mspsb9vt

mspsb9vt2#

此解决方案适用于库https://github.com/ankeetmaini/react-infinite-scroll-component
我使用的结构是基于传递给子组件的道具。父组件正在获取和控制状态。

父组件:

const fetchScrollData = () => {
    // Here we set that we are not able to do scrolling fetching
    setIsLoadingScrollData(true);
    // Apply here some pagination calculation
    searchData()
        .then((tempData) => {
         // Here i am saving the id of the first message
         // I had before scrolling
          setShouldScrollToId(data[0].id);
          const newData = tempData.concat(data);
          setData(newData);
          // Apply here some logic, depending if you have finished or not
          setHasMoreData(true);
        })
        .then(() => {
          setTimeout(() => {
            // Change the timeout accordingly
            // hack for setting the isloading to false when everything is done
            setIsLoadingScrollData(false);
          }, 1500);
        });
  };

子组件

type PropsType = {
  fetchScrollData: () => void;
  hasMoreData: boolean;
  data: string[];
  isLoadingScrollData: boolean;
  shouldScrollToId: string;
};

const ChildComponent: FC<PropsType> = (props: PropsType) => {
  useEffect(() => {
    if (props.shouldScrollToId !== '') {
      const element = document.getElementById(props.shouldScrollToId);
      if (element) {
        element.scrollIntoView({ behavior: 'smooth' });
      }
    }
  });
  ....
  return (
   <div
      className="message-list overflow-scroll"
      id="scrollableDiv"
      style={{
        display: 'flex',
        flexDirection: 'column-reverse'
      }}>
      <InfiniteScroll
          dataLength={props.data.length}
          hasMore={props.hasMoreData && !props.isLoadingScrollData}
          inverse={true}
          next={props.fetchScrollData}
          scrollableTarget="scrollableDiv"
          style={{ display: 'flex', flexDirection: 'column-reverse', perspective: '1px' }}
          loader={<></>}>
          <div>
           {props.data.map((d, index) => {
            // Here i am setting the id which the useEffect will use to do the scroll
            <div key={index} id={d.id} >div - #{message}</div>;
           })}
         </div>
        {props.isLoadingScrollData ? <Spinner></Spinner> : null}
      </InfiniteScroll>
    </div>

我的加载器有一些问题,所以我决定不使用它。相反,我创建了我自己的Spinner组件,并根据显示是否仍在从滚动中获取数据的属性使其出现或消失。

相关问题