javascriptcssreactjsreact-window

react-window with next 13 layout


I have an app with news page, which i'd like to impletement infinite scrolling for. I'm using next 13, and i have app wide nav and footer setup via root layout. I'm trying to use react-window to set it up efficiently, hoever, i'd like to have the react-window scrollbar behaving like a default one, being stuck to the right corner and spannig the full height.

I've got my app width limited to 1920px, whitebars afterwards, and footer and header take some height space.

I've tried tinkering with absolute positions, and fake container divs, but i'm unable to have the corrent scrollbar and footer placement at the same time.

I wasn't able to find any examples showcasing what i'd like to achive. Either the react-window part is fullscreen with nothing else, or other stuff on the page is not accounted for in the scroll bar (it's not full height of the page)

Here's my latest attempt with no luck

function Wrapper({ hasNextPage, isNextPageLoading, items, loadNextPage }) {
  const itemCount = hasNextPage ? items.length + 1 : items.length;

  const loadMoreItems = isNextPageLoading ? () => {} : loadNextPage;

  const isItemLoaded = (index) => !hasNextPage || index < items.length;

  const Item = ({ index }) => {
    let content;
    if (!isItemLoaded(index)) {
      content = "Loading...";
    } else {
      content = items[index].name.first;
    }

    return <div className={styles.item}>{content}</div>;
  };
  const [size, setSize] = React.useState([0, 0]);

  React.useEffect(() => {
    setSize([window.innerWidth, window.innerHeight]);
  }, []);

  return (
    <div className={styles.container}>
      <InfiniteLoader
        isItemLoaded={isItemLoaded}
        itemCount={itemCount}
        loadMoreItems={loadMoreItems}
      >
        {({ onItemsRendered, ref }) => (
          <FixedSizeList
            itemCount={itemCount}
            onItemsRendered={onItemsRendered}
            ref={ref}
            height={size[1]}
            width={size[0]}
            itemSize={35}
          >
            {Item}
          </FixedSizeList>
        )}
      </InfiniteLoader>
    </div>
  );
}

css:

.container {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
}

.item {
  max-width: 1920px;
  margin: 0 auto;
}

Solution

  • I haven't decided if I'm fully dropping global nav and footer from layout or just hiding it for the news page specifically, but here's somewhat of a solution. Prepend the header to the first list item, and append the footer to the last one.

      // Render an item or a loading indicator.
      const Item = ({ index }) => {
        if (!isItemLoaded(index)) {
          return "Loading...";
        }
    
        if (index === 0)
          return (
            <React.Fragment>
              <Nav />
              <Article item={items[index]} />
            </React.Fragment>
          );
    
        if (index === items.length - 1)
          return (
            <React.Fragment>
              <Article item={items[index]} />
              <Footer />
            </React.Fragment>
          );
    
        return <Article item={items[index]} />;
      };