【问题标题】:Why would useRef object be null even after attaching to a div element?为什么 useRef 对象在附加到 div 元素后仍为 null?
【发布时间】:2023-02-04 04:10:09
【问题描述】:

大家好,我在尝试对 div 元素使用 Ref 时遇到了一个奇怪而烦人的问题。我的工作与在另一页上完全一样,但这似乎并没有按照我在该页面上的要求进行。

我正在尝试实现无尽的滚动。目标是将 ref (refetchTrigger) 附加到页面上的某个 div,并在滚动到视图中时触发对下一页数据的提取。它似乎正确地呈现了 div,但 refetchTrigger 没有更新为 div,它只是保持为空。似乎这里需要重新渲染,但显然更改 refs 不会触发重新渲染。我整个上午都在为此苦苦挣扎,非常感谢任何建议。在下面的代码 sn-p 中,所有 console.log(refetchTrigger.current) 都打印出 null。

还值得注意的是,refetch 调用使用 useSWR 挂钩来获取数据。删除它时,将 ref 附加到 div 似乎可以正常工作。此外,在添加按钮以按预期获取其获取时。它只是在尝试自动触发我看到问题的提取时尝试。

谢谢您的帮助!

export const TrackGrid = () => {
  const [list, setList] = useState<Track[]>([]);
  const [page, setPage] = useState<number>(1);
  const refetchTrigger = useRef<HTMLDivElement | null>(null);
  const inViewport = useIntersection(refetchTrigger, "0px");

  const { tracks, error, isValidating } = useGetTracks(false, page, 20);

  useEffect(() => {
    if (inViewport) {
      setPage(page + 1);
    }

    console.log("in viewport");
  }, [inViewport]);

  useEffect(() => {
    if (tracks) setList([...list, ...tracks]);
  }, [tracks]);

  const renderDiv = () => {
    console.log(refetchTrigger.current);
    const d = <div ref={refetchTrigger}>exists</div>;
    console.log(refetchTrigger.current);
    return d;
  };

  return (
    <>
      <div className="grid place-items-center grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
        {!!list.length && renderDiv()}

        {list.map((track: Track, i: number) => {
          console.log(refetchTrigger.current);
          return (
            <div ref={refetchTrigger} key={i}>
              <TrackGridItem track={track} />
            </div>
          );
        })}
      </div>
    </>
  );
};

【问题讨论】:

    标签: reactjs dom infinite-scroll use-ref swr


    【解决方案1】:

    ref 只会被填充渲染完成,元素已通过对实际 dom 的反应创建。在渲染期间注销 ref 将不起作用(除非之前有渲染)。

    解决方法是将需要与 ref 交互的代码放入 useEffect。这样,当您的代码运行时,渲染已完成并且元素位于页面上。

    useEffect(() => {
      console.log(refetchTrigger.current)
    }, []);
    

    【讨论】:

    • 他需要useLayoutEffect。如果他使用useEffect,则 ref 在挂载时将为 null
    • He needs useLayoutEffect 他可能,是的,但那是为了防止闪烁,而不是因为 ref 将为空。 ref 在 useEffect 中将是非空的(假设他将 ref 传递到放置在页面上的某个元素中,例如 &lt;div ref={refetchTrigger}&gt;
    • useEffect 与 refs 一起工作是的,但在您的示例中,您有一个在挂载上运行的 useEffect。如果这是用于 DOM 元素的 ref(即附加到 ref 属性),则在第一次挂载时它不会为 null。但他当然可以做空检查来绕过它。一如既往地“取决于”。
    • 你认为useEffect什么时候运行?顺序是:组件渲染,然后反应更新 dom 和 refs,然后效果运行。
    • 抱歉,那是不对的。组件呈现 != DOM 已提交。 useEffect 在提交 DOM 之前运行。
    【解决方案2】:

    本质上,在整个渲染过程完成之前,不会填充 ref。这对许多 React 程序员来说并不明显(而且通常无关紧要),但 DOM 直到后来才真正提交。当您调用 renderDiv() 并传递 ref 时,在第一次安装时,元素甚至不会在代码执行阶段呈现在 DOM 中。 React 有效地执行和渲染虚拟DOM在渲染过程后不久将树转换为真实的 DOM。

    如果您有依赖于现有 DOM 节点的代码,因为无论出于何种原因您需要读取某些内容,您需要运行它或(这是您必须小心的事情),请在 ref 回调中运行它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-26
      • 2016-05-19
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多