开发者问题收集

无法读取 null 的属性“scrollIntoView”

2021-02-04
35895

为什么它没有按预期工作?有时它可以工作,有时它不工作 - 我无法弄清楚这一点。带有 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
3个回答

它最初不起作用,因为当你的组件函数运行时还没有元素。如果有一些顺序渲染,它会起作用,因为那时有一些元素。然而,这样做仍然是错误的。从 React 访问 DOM 应被视为副作用,纯函数中不能有副作用(并且您的组件 纯函数。

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

我制作了一个小的 fiddle 供您查看,如何在您的案例中使用 ref。

Mr. Hedgehog
2021-02-04

第一次执行此行时,结果为 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);
    }
}
lissettdm
2021-02-04

面临同样的问题,对我有用的是在 setTimeout 的回调中使用 scrollIntoView,延迟 1 秒(或更少)

useEffect(() => {
    setTimeout(() => divRef.current.scrollIntoView({ behavior: 'smooth' }), 1000);
  });
Raj Shankar Tiwary
2022-11-10