ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.05k stars 13.51k forks source link

bug: Collapsed header + Virtual scroll #27793

Closed noskovvkirill closed 1 year ago

noskovvkirill commented 1 year ago

Prerequisites

Ionic Framework Version

v7.x

Current Behavior

Hi! We use <IonHeader collapse="condense" className="ion-padding-start"/> with Virtuoso to create a collapsible header.

  <GroupedVirtuoso
      className="ion-content-scroll-host h-full overflow-scroll"
      endReached={() => {
        if (hasNextPage) {
          fetchNextPage();
        }
      }}
      components={{
         Header: () => {
           return(
          <IonHeader collapse="condense" className="ion-padding-start">
              <IonToolbar>
                    <h1 className="text-h1 font-medium">Notifications</h1>
              </IonToolbar>
          </IonHeader>
        )
        }
        }} 
  ...
  /> 

However, it blinks when the new data is loaded and Virtuoso rerenders. We added a key, tried to memoize it, but nothing helps. Header rerenders, but doesn't disappear from the tree. I've attached a video to show the behaviour.

https://github.com/ionic-team/ionic-framework/assets/50060130/09fd0cb0-e7a6-4460-a486-34619e971a5a

Expected Behavior

No flickering on rerender for condensed Header

Steps to Reproduce

  1. Add Virtual list
  2. Create collapsible Header inside the Virtual list
  3. Append data to Virtual list while you scroll

Code Reproduction URL

No response

Ionic Info

Ionic:

Ionic CLI : 7.1.1 "@ionic/core": "^7.1.1", "@ionic/pwa-elements": "^3.1.1", "@ionic/react": "7.1.0", "@ionic/react-router": "7.1.0",

Utility:

cordova-res : not installed globally native-run : not installed globally

System:

NodeJS : v18.16.0 npm : 9.5.1 OS : macOS Unknown

Additional Information

No response

ionitron-bot[bot] commented 1 year ago

Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.

Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.

If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.

For a guide on how to create a good reproduction, see our Contributing Guide.

noskovvkirill commented 1 year ago

Reproduced it here @liamdebeasi Repo (created from Nextjs Ionic template): https://github.com/noskovvkirill/ionic-reproduction-header-issue Component: https://github.com/noskovvkirill/ionic-reproduction-header-issue/blob/main/components/pages/Feed.jsx

https://github.com/ionic-team/ionic-framework/assets/50060130/06c8861f-c49b-4efc-8817-7d2f021ec745

liamdebeasi commented 1 year ago

The problem here is the header passed in to Header for Virtuoso keeps getting re-created every so often. If the collapsible large title is removed from the DOM, then the main header needs to be updated too.

In this case, the component should be memoized. Instead of using an arrow function, you can use a React component:

function Header() {
  return (
    <IonHeader collapse="condense">
      <IonToolbar>
        <IonTitle size="large">Feed</IonTitle>
      </IonToolbar>
    </IonHeader>
  )
}

....

<Virtuoso 
  components={({ Header })}
/>

edit: See https://github.com/petyosi/react-virtuoso/issues/407

noskovvkirill commented 1 year ago

Thanks @liamdebeasi We ended up keeping the function instead of the component and memoizing it using useCallback / useMemo

ionitron-bot[bot] commented 1 year ago

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.