skip to Main Content

I have an antd list displayed on a page and certain actions elsewhere will cause an item in the list to be selected. I want the item to automatically scroll to it. I can’t figure it out.

The code that displays the list is below.

   <List
                            itemLayout="horizontal"
                            dataSource={courses}
                            className="hoverable-list"
                            bordered
                            renderItem={(item, index) => (
                                <List.Item bordered="true" className={currentCourse == item.course_code ? 'active' : ''} onClick={() => setCurrentCourse(item.course_code)}>
                                    {/* <Tooltip placement="bottomLeft" title={item.description}> */}
                                    <List.Item.Meta
                                        id={item.course_code}
                                        title={item.course_code}
                                        description={item.course_name}
                                    />
                                    {/* </Tooltip> */}
                                </List.Item>
                            )}
                        />

I tried using a getElementByID and then scrolling it into view, but that didn’t seem to do it.

    const scrollToItem = (itemId) => {
        const element = document.getElementById(itemId);
      
        if (element) {
          element.scrollIntoView({ behavior: 'smooth' });
        }
      };

    const handleNodeClick = (nodeId) => {
        setCurrentCourse(nodeId);
        scrollToItem(nodeId);
    }

2

Answers


  1. You need to create a scrollable container for the list. Scroll in the container rather than the HTML document

    e.g.

    import { List } from 'antd';
    import { useLayoutEffect } from 'react';
    
    const data = [
      { id: '1', name: 'a' },
      { id: '2', name: 'b' },
      { id: '3', name: 'c' },
      { id: '4', name: 'd' },
      { id: '5', name: 'e' },
      { id: '6', name: 'f' },
      { id: '7', name: 'g' },
    ];
    
    const scrollToItem = (itemId) => {
      const element = document.getElementById(itemId);
    
      if (element) {
        element.scrollIntoView({ behavior: 'smooth' });
      }
    };
    
    export const App = () => {
      useLayoutEffect(() => {
        scrollToItem('3');
      }, []);
    
      return (
        <div
          id="scrollableDiv"
          style={{
            height: 200,
            overflow: 'auto',
            padding: '0 16px',
            border: '1px solid rgba(140, 140, 140, 0.35)',
          }}
        >
          <List
            dataSource={data}
            renderItem={(item) => (
              <List.Item id={item.id} key={item.id}>
                <List.Item.Meta
                  title={<a href="https://ant.design">{item.name}</a>}
                />
                <div>Content</div>
              </List.Item>
            )}
          />
        </div>
      );
    };
    

    stackblitz

    Login or Signup to reply.
  2. https://stackblitz.com/edit/stackblitz-starters-tuw9cm?file=src%2FApp.tsx

    import { FC, useEffect, useRef, useState } from 'react';
    
    const Div = ({ text, isActive }) => {
      const ref = useRef<any>();
      useEffect(() => {
        if (isActive) {
          ref.current.scrollIntoView({ behavior: 'smooth' });
        }
      }, [isActive]);
      return (
        <div
          ref={ref}
          style={{
            background: isActive ? '#006699' : '#dddddd',
            height: '200px',
            margin: '10px',
          }}
        >
          {text}
        </div>
      );
    };
    
    export const App: FC<{}> = () => {
      const data = [1, 2, 3, 4, 5, 6, 7];
      const [activei, setActivei] = useState(5);
      return (
        <div>
          <div>
            {data.map((item) => (
              <div
                onClick={() => {
                  setActivei(item);
                }}
                key={item}
              >
                {' '}
                {item}{' '}
              </div>
            ))}
          </div>
          {data.map((item, index) => (
            <Div isActive={item === activei} text={item} key={item} />
          ))}
        </div>
      );
    };
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search