#Infinite Scroll - React

5 messages · Page 1 of 1 (latest)

steep meteor
#

Hello, i tried to make an infinite scroll, and its working but i feel like it shouldn't.

Please take a look if you can, thank you;

#

part1

type WSMessage =
  | { type: "initialHistoryItems"; items: IHistoryRoomItem[] }

const History = () => {
  const [historyItems, setHistoryItems] = useState<IHistoryRoomItem[]>([]);
  const [page, setPage] = useState<number>(1);
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [endOfData, setEndOfData] = useState<boolean>(false);
  const [scrollTop, setScrollTop] = useState<number>(0);

  const { user, setUser, ws } = useUserContext();

  const bodyRef = useRef<HTMLDivElement>(null);

  const fetchData = useCallback(() => {
    if (endOfData || isLoading) return;
    setIsLoading(true);
    ws.sendJsonMessage({
      type: "getHistoryItems",
      page: page,
    });
    setPage(page + 1);
  }, [page, isLoading]);
#

part2

  function handleScroll() {
    if (!bodyRef.current) return;
    setScrollTop(bodyRef.current.scrollTop);
  }

  useEffect(() => {
    if (!bodyRef.current) return;

    if (
      bodyRef.current.scrollTop +
        bodyRef.current.clientHeight +
        bodyRef.current.clientHeight / 2 <=
        bodyRef.current.scrollHeight ||
      isLoading
    ) {
      return;
    }

    fetchData();
  }, [scrollTop]);

  useEffect(() => {
    if (
      bodyRef.current &&
      bodyRef.current.clientHeight >= bodyRef.current.scrollHeight
    ) {
      fetchData();
    }
  }, [historyItems]);

  function handleWSMessage(msg: WSMessage) {
    if (msg.type === "initialHistoryItems") {
      setIsLoading(false);
      if (msg.items.length === 0) {
        setEndOfData(true);
        return;
      }
      // Check for same page
      if (historyItems.length !== 0 && historyItems[0]._id === msg.items[0]._id)
        return;
      setHistoryItems((prevState) => {
        return [
          ...prevState,
          ...msg.items,
        ];
      });
    }
  }

  useEffect(() => {
    handleWSMessage(ws.lastJsonMessage);
  }, [ws.lastJsonMessage]);

  return (
      <div
        className="flex flex-grow flex-col overflow-auto"
        ref={bodyRef}
        onScroll={handleScroll}
      >
        {historyItems.map((e) => (
          <HistoryRoomItem {...e} key={e._id} />
        ))}
      </div>
  );
};
#

@ me for anything so i can respond instantly

steep meteor
#

help