I am building a React app that utilizes react-scroll
on the home page. I have a series of div
elements that span the entire viewport (height: 100vh; width: 100vw
) that I am scrolling between, with navigation arrows that you can click to scroll through the webpage (the user still has the option to scroll manually as well). When you select any of the navigation arrows, either up or down, the window scrolls smoothly to the next position, however it stutters in the process. The issue seems to be caused when this.setState
is called in my handleSectionChange
method, as commenting it out resolves the issue, however it also removes the required functionality of updating the navigation arrow values.
// Located in main component and passed as a prop to component that calls it
handleSectionChange(incrementValue) {
// Number of section being scrolled to
var newSectionNumber = this.state.displayedSectionNumber + incrementValue
var prevSection = homeViewSections.sections[newSectionNumber - 1];
var nextSection = homeViewSections.sections[newSectionNumber + 1];
// ID of section below current section to assign "to" property to in Link component
var nextSectionId = "";
// ID of section above current section to assign "to" property to in Link component
var prevSectionId = "";
var downArrowContainer = document.querySelector('.navigationArrowContainer.down')
var upArrowContainer = document.querySelector('.navigationArrowContainer.up')
// Repositions down arrow if intro section is displayed
if (newSectionNumber === 0) {
downArrowContainer.classList.add("homeIntroPosition")
} else {
downArrowContainer.classList.remove("homeIntroPosition")
}
// Displays up arrow if any section other than the first one is displayed
if (newSectionNumber > 0) {
prevSectionId = prevSection.referenceId
upArrowContainer.style.visibility = "initial"
} else {
upArrowContainer.style.visibility = "hidden"
}
this.setState({
displayedSectionNumber: newSectionNumber,
prevSectionId: prevSectionId,
nextSectionId: nextSectionId
})
}
The handleSectionChange
method is passed as a prop to another component which calls it (and is the only method that calls it)
componentDidMount() {
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
handleScroll() {
const vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
const scrollValue = window.scrollY;
const newSectionNumber = Math.round(scrollValue / vh)
this.animateHomeViewNavBar()
this.setHomeViewNavLinkToActive();
if (newSectionNumber !== this.props.currentSectionNumber)
this.props.handleSectionChange(newSectionNumber - this.props.currentSectionNumber)
}
As you can see from the code above, it doesn't seem to be an issue with the number of times that the handleSectionChange
method is called, as the if
condition limits it to only when the section number is changed. I was able to pinpoint the issue to the handleChangeMethod
by commenting out this.animateHomeViewNavbar
and this.setHomeViewNavLinkToActive
methods in various combinations, and the only way to resolve the issue was to comment out the handleSectionChange
method, even with the others being called. Then, as mentioned before, the handleSectionChange
method seems to remove the issue when I comment out this.setState
, however that is of course necessary for the functionality. This is also the only method in the both applicable classes that calls setState
, so there doesn't seem to be any conflict with that.