I have a nav bar function componenent which passes the name of the link to the parent component through onclick callback and its further passed to the main app component. The app component have an object with the name of the link and associated ref. onclick callback in the app component takes the ref from the object based on the link-name passed to it by the underlying component and invokes a window.scrollTo. window.scrollTo works when you click a link for the first time and when the page scrolls if another link is clicked from the sticky navbar, window doesn't scroll again but rather goes back to (0,0) and from there clicking the same link works.
//Call back in the App component.
manageContent(link){
console.log(this.linksData[link].current)
window.scrollTo({
top: this.linksData[link].current.offsetTop,
left: 0,
behavior: 'smooth'
})
}
The above function is passed to Header component
<Header links={data} onclick={this.manageContent} ref={this.headerRef}/>
and in the header links are created using a NavLink function component where onClick would return the link-name back.
What i'm doing wrong, why does scrollTo work on second click once the page scroll to the top but not from the middle of the page or from a scrolled location.
I tried other scroll function as well and wierdly only scrollTo scrolls and that to with scrollOptions, scrollToView, moveTo etc didn't work at all.
I printed out the offsetTop in console and triggering window.scrollTo(0,"offsetTop printed in console"), works fine with no issues.
Here is the code.
App.js
class App extends React.Component {
constructor(props){
super(props);
this.manageContent = this.manageContent.bind(this)
this.state={}
this.sectionRef1 = React.createRef();
this.sectionRef2 = React.createRef();
this.sectionRef3 = React.createRef();
this.sectionRef4 = React.createRef();
this.sectionRef5 = React.createRef();
this.headerRef = React.createRef();
this.heroRef = React.createRef();
}
manageContent(key){
console.log(key)
this.setState({key:key});
}
setActivePage = (key) => {
let refList = [this.sectionRef1,this.sectionRef2,this.sectionRef3,this.sectionRef4,this.sectionRef5]
console.log(key)
console.log(refList[key].current)
if (refList[key].current){
window.scrollTo({behavior: "smooth",top: refList[key].current.offsetTop})
}
}
componentDidUpdate(prevProps, prevState) {
console.log("comp updated")
this.setActivePage(this.state.key)
}
/*
componentDidMount(){
window.addEventListener('scroll', this.scrollListener)
}
componentWillUnmount() {
window.removeEventListener('scroll', this.scrollListener)
}
*/
render(){
return (
<div className="bp-container-full bp-typography" key="app">
<Header links={data.links} onclick={this.manageContent} ref={this.headerRef}/>
<main key="main">
<HeroSection ref={this.heroRef}/>
<div className="bp-main">
<section key="home"className="page" ref={this.sectionRef1}>
<Home/>
</section>
<section key="aboutme" className="page" ref={this.sectionRef2}>
<AboutMe/>
</section>
<section key="sitedetails" className="page" ref={this.sectionRef4}>
<SiteDetails/>
</section>
<section key="contact" className="page" ref={this.sectionRef5}>
<ContactForm/>
</section>
</div>
</main>
<Footer/>
</div>
);
}
}
export default App;
Header.js
class Header extends React.Component {
constructor(props) {
super(props);
console.log(props)
this.linkRef = React.createRef()
this.state = {isOpen:false};
this.headerRef = React.createRef()
}
render() {
const navlink = data.links.map((link,key)=>{
return(
<a href="#" key={link} ref={this.linkRef}
className="nav-list-item bp-upper"
onClick={() => this.props.onclick(key)}>
{link}
</a>
)})
return (
<header key="header-key" className={classnames("bp-header","bp-header-fixed",
{"is-scrolled":this.state.scrolled})} ref={this.headerRef}>
<button className={classnames("bp-mobile-menu",{"is-open":this.state.isOpen})} onClick={()=>{this.setState({isOpen:!this.state.isOpen})}}>
<i className={classnames("fas", {"fa-bars":!this.state.isOpen, "fa-times":this.state.isOpen})}></i>
</button>
<div className={classnames("nav", "nav-align-centre",{"is-open":this.state.isOpen})}>
<nav className="nav-list nav-primary">
{navlink}
</nav>
</div>
</header>
)
}
}
export default Header;