DEV Community

Cover image for Autoscrolling lists with React Hooks
Patrick Jones
Patrick Jones

Posted on • Updated on

Autoscrolling lists with React Hooks

Create a container

To start, create a component that recieves a list of [items] and displays each item by mapping over the list.

export const AutoScrollContainer = ({ items }) => {
    return (
        <div className="autoscroll-container">
            <div className="scroll-list">
                {items && items.map((item, index) => 
                    <p key={index}>{`${index + 1}. ${item}`}</p>
                )}
            </div>
        </div>
    )
}

React's useRef hook will provide a reference to a DOM element at the bottom of the list. Then we can use the browser's scrollIntoView() API to do the scrolling for us.

export const AutoScrollContainer = ({ items }) => {
    const bottomRef = useRef();

    const scrollToBottom = () => {
        bottomRef.current.scrollIntoView({
        behavior: "smooth",
        block: "start",
        });
    };
    return (
        <div className="autoscroll-container">
        <button type="button" onClick={scrollToBottom}>
            Scroll To Bottom
        </button>
        <div className="scroll-list">
            {items &&
            items.map((item, index) => (
                <p key={index}>{`${index + 1}. ${item}`}</p>
            ))}
            <div ref={bottomRef} className="list-bottom"></div>
        </div>
        </div>
    );
};

Add a button to trigger the scroll and watch the magic happen before your eyes.

Press to scroll

That's pretty neat! But at this point this is nothing auto about this solution. To fix this, we can react to changes in [items] using useEffect to trigger the scroll from there. I'm adding another useEffect hook to handle the initial mount as well.

export const AutoScrollContainer = ({ items }) => {
    ...

    useEffect(() => {
        scrollToBottom()
    }, [items])

    useEffect(() => {
        scrollToBottom()
    }, [])

    ...
}

Let's also add a some logic to mock live data.

const ITEMS = "perferendis asperiores adipisci voluptatibus autem repellendus".split(" ")
export const App = () => {
    ...
    // Add a new item to `items` every second.
    useEffect(() => {
        let interval = setInterval(() => {
            let item = ITEMS[Math.floor(Math.random() * ITEMS.length)];
            setItems([...items, item])
        }, 1000);

        // remember to clear timers
        return function cleanup() {
            clearInterval(interval);
        };
    });
}

Conclusion

You now have an auto-scrolling react component! You could implement an infinite scroll to handle very large lists of live data if you felt inclined.

Auto Scroll

Top comments (0)