Search code examples
reactjstailwind-css

scrollLeft not working on a element accessed by useRef


So I have a container of elements, whenever I add a new element, I want it to scroll all the way to the right using scrollLeft. I access the container div via useRef and set its classname as overflow-x-scroll but it seems not working whether I dynamically calculate the distance for scrolling or set a fixed one.

Below is my implementation:

const thumbnailContainer = useRef<HTMLDivElement>(null)
const addPage = () => {
        editor?.setPageContainer(prev => [...prev, editor?.pageContainer.length])
        editor?.setCurrentPage(editor?.pageContainer.length)
        if (thumbnailContainer.current) {
            const maxScrollLeft =
                thumbnailContainer.current.scrollWidth - thumbnailContainer.current.clientWidth;
            thumbnailContainer.current.scrollLeft += maxScrollLeft;
        }
    }
return (
        <div
            className='h-[130px] top-[calc(100%-170px)] items-center absolute z-50 bg-gray-200 flex p-2 gap-5 overflow-x-scroll'
            style={style} ref={thumbnailContainer}>
            {editor?.pageContainer?.map((i) => {
                return <TooltipProvider key={i}>
                    <Tooltip delayDuration={200}>
                        <TooltipTrigger className={`h-[80%] min-w-[140px] flex justify-center items-center`}>
                            <Button  variant='outline'
                                     className={`h-full min-w-[100%] ${editor?.currentPage === i && 'border border-black'}`}
                                    onClick={() => handleChangePage(i)}>
                            </Button>
                        </TooltipTrigger>
                        <TooltipContent side="top" sideOffset={10}>
                            <p>Page {i + 1}</p>
                        </TooltipContent>
                    </Tooltip>
                </TooltipProvider>
            })}
            <Button variant='outline' className='h-[80%] min-w-[140px] shrink-0 grow-0 flex justify-center items-center text-5xl' onClick={addPage}>+</Button>
        </div>
    );

Solution

  • import { useEffect, useRef, useState } from "react";
    import "./styles.css";
    
    const App = () => {
      const scrollToDiv = useRef(null);
      const [items, setItems] = useState(["hi", "hello", "master"]);
      const generateRandomWord = () => {
        const word = "demo";
        setItems((prev) => {
          return [...prev, word];
        });
      };
    
      useEffect(() => {
        if (scrollToDiv.current) {
          scrollToDiv.current.scrollIntoView({
            behavior: "smooth",
            block: "nearest",
          });
        }
      }, [items]);
    
      return (
        <div className="container">
          <div className="x_container">
            {items?.map((a, i) => {
              return (
                <span key={i}>
                  {i + 1}. {a}
                </span>
              );
            })}
            <div ref={scrollToDiv}></div>
          </div>
          <button onClick={generateRandomWord}>Add random word</button>
        </div>
      );
    };
    
    export default App;
    .container {
      display: flex;
      flex-direction: column;
      gap: 1rem;
      justify-content: center;
      align-items: center;
    }
    
    .x_container {
      display: flex;
      gap: 8px;
      border: 1px solid grey;
      width: 300px;
      overflow-x: scroll;
      padding: 1rem 0.5rem;
    }
    
    .x_container span {
      text-wrap: nowrap;
    }
    .x_container::-webkit-scrollbar {
      /* display: none; */
    }

    hey if you're looking for something like this: everytime new item adds up to list it should scroll to last item , you can use this

    https://codesandbox.io/p/sandbox/gy9qrg