Search code examples
reactjsscrollrendering

How to make React app scroll to a specific element on a newly rendered page?


I am struggling to find information about how to make React app scroll to a specific element on a newly rendered page after clicking a corresponding element. I have a homepage with 6 service cards. I also have a services page that includes more detailed descriptions about each service. I want the browser to automatically scroll to a corresponding service in the services page after a card in homepage was clicked.

Here is the Card component in the homepage:


    const navigate = useNavigate()

    return (
        <div id={data.id} className="serviceCard slideUpContainer" onClick={() => navigate(data.link)}>
            <img src={require('../visuals/' + data.img + '.png')} alt={data.title} />
            <div className="slideUpContent">
                <h2 className="slideUpTitle">{data.title}</h2>
                <p className="slideUpText">{data.excerpt}</p>
                <div className="linkContainer">
                    <a href={data.link}>{data.btn}<i className="glyphicon glyphicon-menu-right"></i></a>
                </div>
            </div>
        </div>
    )
}
export default ServiceCard

And here is the Service component in the services page:



    return (
        <div id={data.id} className={data.className}>
        <div id="imgBox">
            <img src={require('../visuals/services/' + data.blockImg + '.png')}
            alt={data.alt} />
        </div>
        <div id="textBox">
            <h2>{data.title}</h2>
            <p>{data.description}</p>
            <div>
                <h3>{data.listName}</h3>
                <ul>
                    {data.listItems.map(item => 
                        <ServiceListItem key={nanoid()} data={item} />
                        )}
                </ul>
            </div>
        </div>
    </div>
    )
}

For now I was using navigate(), I also tried adding /#ElementID to the url and neither of those gives me the desired result. I was trying to find more info on the internet, but all I get is the scrolling option on the same page (which is easy).


Solution

  • Newly rendered page means that you can use an empty dependencies 'useEffect' as a callback for when the component you want into view finishes rendering and is available in the DOM:

    useEffect(() => {
        document.getElementById("ElementID").scrollIntoView();
        // or, use a ref and
        elementRef.current.scrollIntoView()
    }, [])
    

    You can also use on any parent component of the component you want into view, as parent's 'onEffect' is always called after a child has completely rendered (and its own 'onEffect' has already ran).

    To complement this, you can also use in your CSS:

    • scroll-padding-top - if you have a sticky header or somehow the scroll doesn't center the element correctly
    • scroll-behavior - for smooth scrolling, if you want this feature. If you want your page to instant scroll to this component, but have smooth scroll for everything else, you can also: disable smooth scroll -> scrollIntoView() -> re-enable smooth scroll.