Cannot read property 'scrollIntoView' of null

11,024

Solution 1

It does not work initially because by the time your component function run there is no elements yet. And it works if there were some sequential renders, since at that time there is some elements. However, it is still wrong way to do this. Accessing DOM from react should be considered side effect and you can't have side effects in pure functions (and your component is pure function.

In functional react components you can tackle side effects in few ways. One of this ways (and often is the best way) is hooks. If you want to store some mutable data (as DOM element) it is good to use useRef hook. This way React will set ref to DOM element and it can be passed by reference into your event handler. You still will need to check if element is actually exists, but with getElementById you should do the same.

I made small fiddle for you to look, how you can use refs for your case.

Solution 2

The first time this lines are evaluated to null because the components have not been rendered yet:

   const reftp = document.getElementById("refTP");
   const refpp = document.getElementById("refPP");

Move the element reference to handleClick function:

const handleClick = (id) => {
   const reftp = document.getElementById("refTP");
   const refpp = document.getElementById("refPP");
    if(id === 0 && page===true){
        reftp.scrollIntoView({ behavior: "smooth" });
        setPage(false);
    } else if(id === 1 && page===false){
        refpp.scrollIntoView({ behavior: "smooth" });
        setPage(true);
    }
}
Share:
11,024

Related videos on Youtube

Emil Woxen
Author by

Emil Woxen

Updated on May 30, 2022

Comments

  • Emil Woxen
    Emil Woxen almost 2 years

    Why isn't this working as expected? Sometimes it works, and sometimes it doesn't - i cannot figure this one out. The piece of code with ScrollIntoView was copied from another js file with another page, and in that one it works just fine? The ID's refTP and refPP are found within div tags in ReferencesPP and ReferencesTP

    import React, {useState} from 'react'
    import ReferencesPP from './referencesPP'
    import ReferencesTP from './referencesTP'
    import "./references.css"
    
    function ReferencesPage(){
        const reftp = document.getElementById("refTP");
        const refpp = document.getElementById("refPP");
    
        const [page, setPage] = useState(false);
    
        const handleClick = (id) => {
            if(id === 0 && page===true){
                reftp.scrollIntoView({ behavior: "smooth" });
                setPage(false);
            } else if(id === 1 && page===false){
                refpp.scrollIntoView({ behavior: "smooth" });
                setPage(true);
            }
        }
    
        return(
            <div className="references-main-container">
                <ul>
                    <li id="anchor1" onClick={()=>handleClick(0)}></li>
                    <li id="anchor2"onClick={()=>handleClick(1)}></li>
                </ul>
                <ReferencesTP />
                <ReferencesPP />
            </div>
        )
    }
    
    export default ReferencesPage
    
  • Emil Woxen
    Emil Woxen about 3 years
    I did not know this - so thanks a bunch! How would one go about fetching the ref from another component? Like the way i use .getElementById in the code above?
  • Emil Woxen
    Emil Woxen about 3 years
    Nevermind - thanks a bunch, i found out. One question, what does if(!ref.current) return; do exactly?
  • Mr. Hedgehog
    Mr. Hedgehog about 3 years
    Since it is a mutation on value, you can't be sure that you have value you want on ref. This is just a precaution that value will be there when you will try to access it. Otherwise it will just exit function without doing anything and without raising an error. You can otherwise use try/catch to handle such error, or if you have 200% confidence in your code and react code and anything in between, you can omit said precautions. I try not to trust myself too much and check, just to be sure.
  • Mr. Hedgehog
    Mr. Hedgehog about 3 years
    Just in case, someone will be reading this in the future, I'll answer about refs on child components. It can be achieved with ref forwarding.