https://abc1234.com/users#api-doc
<div className={parent}>
<div className={child}>
{someContent}
<a id="api-doc">Hello API</a>
</div>
</div>
I am writing the page in ReactJS. I need to implement a way so that the page should auto-scroll down to the Hash i.e. api-doc but somehow it's not auto-scrolling on page load (very first time).
I tried a workaround which is like this
componentDidUpdate(){
let id = this.props.history.location.hash.replace("#", "");
let element = document.getElementById(id);
setTimeout(() => {
if (element) {
element.scrollIntoViewIfNeeded(true);
}
}, 200);
}
It's working but I am looking for a better way to achieve the same
In other words, I do not want to use setTimeOut.
I added setTimeOut cause I found that document.getElementById(id) is giving null (very first time), I am assuming that somehow componentDidUpdate is running before the entire render. I have also used dangerouslySetInnerHTML .
You are correct that document.getElementById(id)
returns null
because the element has not yet rendered.
With React do not use document.getElementById()
.
React nodes are not real DOM nodes (e.g., text or element nodes) themselves, but a representation of a potential DOM node.
Instead, use the hook useRef()
React documentation
Create the following component.
import React, { useRef, useEffect } from 'react';
const myComponent = (props) => {
const myRef = useRef();
function scrollToComponent() {
if (window.location.hash === '#api-doc') {
myRef.current.scrollIntoView();
myRef.current.focus();
}
}
useEffect( () => scrollToComponent(), [] )
return (
<div ref={myRef} id="api-doc">
...
</div>
)
};
export default myComponent;
Using useEffect
this way will (only) trigger when the component mounts. (therefore avoiding the issue of the JS running before the component has mounted)
The function I have named scrollToComponent
will check the URL for a hash, if it passes the condition, it will scroll to the ref.
Remember to import the component to your main file.
*Note: using Link from React router may be a better solution. (but one I'm not familiar with)