I've been trying to resolve that error since yesterday, but still no luck. I'll explain briefly.
Expectations
I'm using React ScrollSpy Nav Library to implement active link highlighting feature on the webpage according to the currently scrolled article's id.
Don't get confused by the way I set the links, I'm just using reacti18next to adapt links for different languages, thus it's easier to dynamically add them and limit copy paste.
I want the active link to be highlighted, and onClick -+- to scroll to the desired article by its id.
When the onScroll event gets called, I get an error "Cannot read property classList of null" when the script attempts to add or remove .is-active className. I've been trying to solve it and came with a conclusion that what happens is (in ascending order, reversed):
3)
this.scrollTargetIds.forEach(function (r, n) {
document.getElementById(r) ? (e = document.getElementById(r).offsetTop - (t.headerBackground ? document.querySelector("div[data-nav='list']").scrollHeight : 0), window.pageYOffset - t.offset >= e && window.pageYOffset < e + document.getElementById(r).scrollHeight ? (t.getNavLinkElement(r).classList.add(t.activeNavClass), t.clearOtherNavLinkActiveStyle(r)) : t.getNavLinkElement(r).classList.remove(t.activeNavClass), window.innerHeight + window.pageYOffset >= document.body.scrollHeight && n === t.scrollTargetIds.length - 1 && (t.getNavLinkElement(r).classList.add(t.activeNavClass), t.clearOtherNavLinkActiveStyle(r))) : console.warn("".concat("react-scrollspy-nav", ": no element with id ").concat(r, " present in the DOM"));
});
t.getNavLinkElement(r) returns null, because (here is the implementation of that function - getNavLinkElement):
2)
getNavLinkElement(sectionID) {
return document.querySelector(`a[href='${this.hashIdentifier}${sectionID}']`);
}
Because here this is undefined, as I explored in the devtools debugger scope's block. This is undefined there, yet r and n are = "definitions" and 0 (as expected)
3)
And here's where the this.hashIdentifier gets set:
constructor(props) {
super(props);
this.props = props;
this.scrollTargetIds = this.props.scrollTargetIds;
this.activeNavClass = this.props.activeNavClass;
this.scrollDuration = Number(this.props.scrollDuration) || 1000;
this.headerBackground = this.props.headerBackground === "true" ? true : false;
this.offset = this.props.offset || 0;
this.onScroll = this.onScroll.bind(this);
if(this.props.router && this.props.router === "HashRouter") {
this.homeDefaultLink = "#/";
this.hashIdentifier = "#/#";
} else {
this.homeDefaultLink = "/";
this.hashIdentifier = "#";
}
}
Classe's constructor
Here's my React code where I initialize the React Scrollspy Nav component, and set the links, and so on. It's Navigation component:
export const LeftSideNavigation = () => {
const {t} = useTranslation();
const [isLoaded, setIsLoaded] = React.useState(false);
React.useEffect(() => {
if (!document) {
return;
}
if (!document.querySelector) {
return;
}
if (document.querySelector("#articles-wrapper")) {
console.log(isLoaded)
if (!(document.querySelector("#articles-wrapper") as Element).innerHTML) {
return;
}
console.log((document.querySelector("#articles-wrapper") as Element).innerHTML)
setIsLoaded(true);
}
else{
console.log("cannot find ekement with id articles wrapper")
}
}, []);
React.useEffect(() =>{
console.log("is loaded is", isLoaded);
}, [isLoaded])
const [Arr, setArr] = React.useState(window.location.toString().includes("termsOfService") ? SubLinks1 : SubLinks2);
return (
<Container>
{isLoaded &&
(<ScrollspyNav
scrollTargetIds={[...Arr.map((link : LinkItem) => {return(camelize(t(link.name)))})]}
offset={100}
activeNavClass="is-active"
scrollDuration="1000"
headerBackground="true"
><ul>
_{
Arr === SubLinks1 ? (<ExpandableLink higherLevelLink="termsOfService" name="conditionsPages.termsOfServiceLinkText" subLinks={SubLinks1} />) : (<ExpandableLink higherLevelLink="privacyPolicy" name="conditionsPages.privacyPolicyLinkText" subLinks={SubLinks2} />)
}
</ul>
</ScrollspyNav>)
}
</Container>
)
}
It's articles component:
<ArticlesContainer id="articles-wrapper">
<Wrapper id="definitions"><Title variant="h4">{t("privacyArticles.1.title")}</Title><Content><Trans i18nKey="privacyArticles.1.content"/></Content></Wrapper>
I want to understand why is "this" undefined.
Important note!
The code blocks I attached (besides the React component's one) are from react-scrollspy-nav node_module's folder, so I can't edit the code in those functions. I can only edit the React component's code.
PS: I installed the package via npm (to be more precise - yarn), and here's the github full source code for that lib: https://github.com/StephenWeiXu/react-scrollspy-nav. Please view it if I haven't provided enough code pieces. The lib used to work a few days ago, but I deleted the project's files by a coincidence, couldn't restore and now reimplementing everything.