petyosi / react-virtuoso

The most powerful virtual list component for React
https://virtuoso.dev
MIT License
5.13k stars 299 forks source link

[BUG] Unable to scroll to absolute bottom if there is a footer with position: sticky #1071

Closed yelnyafacee closed 4 months ago

yelnyafacee commented 4 months ago

Describe the bug I have setup virtuoso with a position: sticky; Footer (<ExpiredNotice />):

CSS:

    "& div.virtuoso": {

        "& section:last-of-type": {

            position: "sticky",
            bottom: "16px",
            paddingLeft: "16px",
            paddingRight: "16px",
            marginTop: "30px",

        },

    }

CODE:

            <Virtuoso
                ref={ref}
                className={"virtuoso"}
                style={{
                    ....
                }}
                context={{ ... }}
                totalCount={props.messages.length}
                itemContent={
                    (index) => {

                        return (

                            <Message
                                ref={el => (allMessageRefs.current[index] = el)}
                                key={index}
                                index={index}
                                message={props.messages[index]}
                            />

                        )

                    }
                }
                headerFooterTag="section"
                components={{
                    Header: () => (
                        <loadMore />
                    ),
                    Footer: () => (
                        <ExpiredNotice />
                    )

                }}
            />

I want the container <div> (<div data-test-id="virtuoso-scroller" ....>) to scroll to the absolute bottom when button is clicked / triggered. but it seems impossible when the Footer <div> container itself is position: sticky;

ScollToIndex Code:

  ref.current?.scrollToIndex({
      index: props.messages.length - 1,
      behavior: "instant",
  })

the above scroll the to bottom of the last element of the list, before the Footer <div>

Expected behavior To be able to scroll to the absolute bottom of the scrollable <div> even when the last child is a sticky Footer. Looking for a solution or just any workaround that will make it possible

Screenshots vid2121

petyosi commented 4 months ago

The Virtuoso component does not anticipate a sticky footer element. I see that you're building a chat interface. I strongly recommend you use the VirtuosoMessageList for that purpose - it solves quite a few specifics of the chat interface, including a dedicated sticky footer component.

yelnyafacee commented 4 months ago

I see, thanks for the reply, VirtuosoMessageList will solve the issues I face above? is there a monthly subscription pricing instead of a full year subscription? the pricing seems little expensive

petyosi commented 4 months ago

Yes, the scrolling API of the message list takes into account the sizing of the sticky elements. The pricing is yearly based. A monthly subscription does not make sense for that kind of offering.

yelnyafacee commented 4 months ago

why is it that in Virtuoso Message List the message data is stored in a ref instead of a reactState? this seems to make it more difficult to manage, unlike Virtuoso which I can just modify (add /remove) from the state array directly

petyosi commented 4 months ago

This section of the docs explains it.

In the case of the message list, an updated data prop may have different underlying reasons - new incoming messages, older messages being loaded, or existing messages being updated (for example, someone liked a message). Reverse-engineering the intent from the data set is not always possible, and it's not always clear how the scroll position should be adjusted. The imperative API gives you the necessary control over the scroll position adjustment that the current data set change should cause.

yelnyafacee commented 4 months ago

Then what should I do with the <VirtuosoMessageList /> initialData={} when I clicked the load More button to load older messages? prepend() to the ref? append to the ref? does the ref even hold the initialData anymore? or do I manually prepend / append to it?

are prepend and append the only options? cant I just do something like:

ref.current?.data = messages

?

previously all I need to do is just:

setMessages([...response_messages, ...messages]);

in the fetchMessages() async axios call

petyosi commented 4 months ago

Follow the tutorial. It covers exactly this - the initial load data and several additional common scenarios.

yelnyafacee commented 4 months ago

the complete live example do not even show the complete code, imports etc, why not just use codesandbox instead?

while the virtuoso tutorial is easily understandable

the virtuoso mesasge list is a mix of javascript and .tsx?

petyosi commented 4 months ago

I'm sorry for wasting your time. It looks like the product and my suggestions do not work for you. Good luck finding a solution that fits your requirements.