jaredLunde / masonic

🧱 High-performance masonry layouts for React
https://codesandbox.io/s/0oyxozv75v
MIT License
797 stars 49 forks source link

List of Masonry: scroll to list index #102

Closed nowiko closed 2 years ago

nowiko commented 2 years ago

DISCLAIMER: Sorry, this is more question, than a bug. But I wasn't able to found some references regarding my case.

Hello, I am trying to create a list of masonries and I would like to have an ability to scroll to particular list item (which is a masonry), this simple example works pretty well:

    const {mediaItems} = props;
    const [scrollIndex, setScrollIndex] = React.useState(0);

    return (
        <div className={style("container")}>
            <button onClick={() => setScrollIndex(0)}>Scroll to 0</button>
            <button onClick={() => setScrollIndex(1)}>Scroll to 1</button>
            <List
                items={[{id:1}, {id:2}]} //dumy list data
                rowGutter={32}
                scrollToIndex={scrollIndex}
                render={({index}) => (<Masonry
                    key={mediaItems}
                    items={mediaItems}
                    columnGutter={8}
                    overscanBy={2} // Pre-renders 2 windows worth of content
                    render={MediaItem} // media item is a component wich fetch the image from the side API and put base64 into the src
                />)}/>
        </div>
    );

but it's not very flexible and I would like to use advanced useScrollToIndex hook. I took code from official example, and my code looks like:

    const {mediaItems} = props;
    const containerRef = React.useRef(null);
    const [windowWidth, height] = useWindowSize();
    const {offset, width} = useContainerPosition(containerRef, [
        windowWidth,
        height
    ]);
    const positioner = usePositioner({width, columnGutter: 8});
    const role = "list";
    const {scrollTop, isScrolling} = useScroller(offset);
    const resizeObserver = useResizeObserver(positioner);
    const scrollToIndex = useScrollToIndex(positioner, {
        offset,
        height,
        align: "center"
    });

    return (
        <div className={style("container")}>
            <button onClick={() => scrollToIndex(1)}>Scroll to 1</button>
            {useMasonry({
                resizeObserver,
                positioner,
                scrollTop,
                isScrolling,
                height,
                containerRef,
                role,
                items: [{id: 1}, {id: 2}],
                render: (props) => (
                    <Masonry
                        key={mediaItems}
                        items={mediaItems}
                        columnGutter={8}
                        overscanBy={1} // Pre-renders 3 windows worth of content
                        render={MediaItem}
                    />
                )
            })}
        </div>
    );

but in this case, is see tickling image placeholders (they are "jumping" a little bit) for second or two, and then page crashes with the following console output: console_errors

Maybe I am missed something, related to the useScrollToIndex in the docs, or I am trying to hammer nails with a microscope ? Can somebody help me?

Best regards, Viktor.

jaredLunde commented 2 years ago

Hmm I've never composed the two components like this. Would you mind reproducing a basic example in CodeSandbox?

nowiko commented 2 years ago

@jaredLunde sure, here is the first example - it renders two identical cats grids as list items, and I am able to scroll to second grid via simple state update. Here is the link to the advanced example, based on useScrollToIndex which using hooks - link , please note that it might kill browser, as there is some kind of memory leak occurs. Please let me know, if I should provide some additional details.

nowiko commented 2 years ago

As this issue is not relevant to me, I mark it as closed.