【问题标题】:Cannot read property 'scrollIntoView' of null无法读取 null 的属性“scrollIntoView”
【发布时间】:2021-02-05 04:39:05
【问题描述】:

为什么没有按预期工作?有时它有效,有时它不起作用 - 我无法弄清楚这一点。 ScrollIntoView 的代码是从另一个页面的另一个 js 文件中复制的,在那个页面中它工作得很好吗? ID 的 refTPrefPP 位于 ReferencesPPReferencesTP 的 div 标签中

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

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    它最初不起作用,因为在您的组件函数运行时还没有元素。如果有一些顺序渲染,它就可以工作,因为那时有一些元素。但是,这样做仍然是错误的方法。从 react 访问 DOM 应该被视为副作用,并且您不能在纯函数中产生副作用(并且您的组件 is 纯函数。

    在功能性反应组件中,您可以通过几种方式解决副作用。其中一种方法(通常是最好的方法)是钩子。如果您想存储一些可变数据(作为 DOM 元素),最好使用 useRef 挂钩。这样,React 会将 ref 设置为 DOM 元素,并且可以将其 通过引用传递 到您的事件处理程序中。您仍然需要检查元素是否确实存在,但使用 getElementById 您应该这样做。

    我做了一个小fiddle 给你看,你可以如何为你的案例使用参考。

    【讨论】:

    • 我不知道这个 - 非常感谢!如何从另一个组件中获取 ref?就像我在上面的代码中使用.getElementById 的方式一样?
    • 没关系 - 非常感谢,我发现了。一个问题,if(!ref.current) return; 到底是做什么的?
    • 因为它是值的突变,你不能确定你在 ref 上有你想要的值。这只是一个预防措施,当您尝试访问它时,价值就会出现。否则它只会退出函数而不做任何事情并且不会引发错误。否则,您可以使用 try/catch 来处理此类错误,或者如果您对代码和反应代码以及介于两者之间的任何内容有 200% 的信心,则可以省略上述预防措施。我尽量不要太相信自己并检查一下,只是为了确定。
    • 以防万一,将来有人会读到这个,我会回答关于子组件的参考。可以通过ref forwarding实现。
    【解决方案2】:

    因为组件还没有被渲染,所以这行第一次被评估为null

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

    将元素引用移动到handleClick函数:

    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);
        }
    }
    

    【讨论】:

      【解决方案3】:

      你错过了current 道具

       reftp?.current.scrollIntoView()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-20
        • 1970-01-01
        • 2022-11-22
        • 2020-04-27
        • 2019-02-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多