在 React 中存储页面偏移值的最佳方式

Best way to store page offset value in React

存储和显示滚动事件改变的页面偏移值的最佳way/recommended模式是什么?

  1. 将值存储在 useState
function App() {

  const [posY, setPosY] = useState(0);

  useEffect(() => {
    const handleScroll = (e) => setPosY(window.pageYOffset);
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  });

  return <div>{posY}</div>;
}
  1. 将值存储在 useRef
function App() {

  const posYRef = useRef(0);

  useEffect(() => {
    const handleScroll = (e) => {posYRef.current = window.pageYOffset};
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  });

  return <div>{posYRef.current}</div>;
}
  1. 直接访问并写入 innerHTML(好吧...我是认真的)
function App() {

  useEffect(() => {
    const handleScroll = (e) => {
      document.querySelector("div").innerHTML = window.pageYOffset;
    );
    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  });

  return <div>{0}</div>;
}

我知道#1 通常被认为是正确的执行,但我想知道在这种情况下#2 或#3 是否一定是错误的。我们可以实际上 做#2 或#3 因为它们在这种情况下才有效吗?

你应该为此使用状态,因为你想在滚动的基础上显示动画,你应该更新状态,并且状态变化会触发重新渲染。 虽然设置 innerHTML 不会重新呈现。

经过一段时间的额外研究,我得出结论,以上三种方法都可以在特殊情况下使用,尽管 #1 绝对是 standard/recommended 方法。

虽然我同意 state 应该在大多数情况下用于在 React 渲染上获得适当的更新,但 #2 或 #3 也可以工作 如果页面在加载后从未更新。它尤其适用于非 React 支持的第三方库正在操纵 DOMs,并且您需要使用 React 更新它们。它是 React 反模式,可能会造成维护地狱,因此您在执行 #2 或 #3 时应该知道自己在做什么。

关于性能,#2 或#3 理论上应该更快,因为它们都跳过虚拟 DOM 更新。但是,在正常情况下,操作几百个 DOM 个元素时几乎没有区别;这意味着在大多数情况下,使用 #2 或 #3 无法获得更好的渲染性能。