skip to Main Content

So I have a react functional component. In this component, there is a section that checks for the loading state. If it is loading, then I return this other component that is a template placeholder. When it is not loading, then I render this component of data (a long list of names where you have to scroll to reach the bottom). It only shows 20 names at a time then has to fetch more names which causes the loading attribute to be true.

But the current issue is that whenever loading is true, it returns the placeholder component, then RE RENDERS the component of names, which always displays the top of the list. So whenever I am scrolling, it keeps jumping to the top, and I can never reach the bottom.

Does anyone have any solutions?

const ExampleComponent: React.FC<IProps> = ({
const { loading } = customHook({...});
if (loading) {
    return (
      <Placeholder/>
    );
  }

return <VirtualizedTreeNamesList/>;
})

3

Answers


  1. Try this

    const MemoizedVirtualizedTreeNamesList = React.memo(VirtualizedTreeNamesList);
    
    const ExampleComponent: React.FC<IProps> = () => {
      const { loading } = customHook({...});
    
      if (loading) {
        return (
          <Placeholder />
        );
      }
    
      return <MemoizedVirtualizedTreeNamesList />;
    };
    
    Login or Signup to reply.
  2. You can use a ref to maintain a reference to the VirtualizedTreeNamesList component, so it doesn’t reset its scroll position when the component re-renders.
    something like this

    
    const ExampleComponent: React.FC<IProps> = () => {
      const { loading } = customHook({...});
    
      const virtualizedTreeRef = useRef(null);
    
      const scrollToBottom = () => {
        if (virtualizedTreeRef.current) {
          const listContainer = virtualizedTreeRef.current;
          listContainer.scrollTop = listContainer.scrollHeight;
        }
      };
    
      if (loading) {
        return <Placeholder />;
      }
    
      return (
        <div ref={virtualizedTreeRef} style={{ overflowY: 'scroll', maxHeight: '400px' }}>
          <VirtualizedTreeNamesList onScrollToBottom={scrollToBottom} />
        </div>
      );
    };
    

    Now from your VirtualizedTreeNamesList component you just need to call this function passed as props, in the child component VirtualizedTreeNamesList it should be a state example there, that once updated, you want to adjust the height of the parent component i.e call props.scrollToBottom()

    useEffect(()=> {
     props.scrollToBottom()
    },[example])
    

    or you just call props.scrollToBottom() when you need to.

    Login or Signup to reply.
  3. To solve this problem, you can use the React useRef hook to maintain the reference to the VirtualizedTreeNamesList component and prevent it from unmounting and remounting when the loading state changes. Here’s how you can do it:

    import { useRef } from 'react';
    
    const ExampleComponent: React.FC<IProps> = ({
      const { loading } = customHook({...});
      const virtualizedTreeRef = useRef(null);
    
      if (loading) {
        return (
          <Placeholder/>
        );
      }
    
      return <VirtualizedTreeNamesList ref={virtualizedTreeRef} />;
    })
    

    Now, within the VirtualizedTreeNamesList component, you need to ensure that it supports forwarding the ref to the underlying container that holds the scrollable list. You can do this using the React.forwardRef function:

    const VirtualizedTreeNamesList = React.forwardRef((props, ref) => {
      // Your existing code for the VirtualizedTreeNamesList component
      // ...
    
      return (
        <div ref={ref}>
          {/* Your list rendering logic */}
        </div>
      );
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search