【问题标题】:React ref.current is undefined in useLayoutEffectReact ref.current 在 useLayoutEffect 中未定义
【发布时间】:2020-11-03 17:19:36
【问题描述】:

我正在尝试为项目的水平滚动部分实现 POC。我在水平可滚动部分上方有 3 个彼此相邻的 h3,这些 h3 应该对应于水平位中的各个子部分。

我正在使用 react-intersection-observer 创建子部分的引用,以便在用户单击其中一个 h3 时能够滚动到它们。 状态设置正确,在 React Dev Tools 中,我可以看到 useInView 钩子设置正确,并将 s 显示为 refs。但是,当我尝试在任何地方访问 refOne.current 时,它会返回未定义。我在这里明确使用 useLayoutEffect 来等待所有 DOM 节点被完全绘制,但 refOne.current 仍然是未定义的。

import React, { useState, useLayoutEffect } from 'react';
import { useInView } from 'react-intersection-observer';
import classNames from 'classnames';

import classes from './Projects.module.css';
const Projects = () => {
    const [activeState, setActiveState] = useState('one');

    let [refOne, inViewOne, entryOne] = useInView({
        threshold: 1,
    });

    let [refTwo, inViewTwo, entryTwo] = useInView({
        threshold: 1,
    });

    let [refThree, inViewThree, entryThree] = useInView({
        threshold: 1,
    });

    useLayoutEffect(() => {

        console.log(refOne.current) // comes back undefined

        checkAndScroll(activeState);
    }, [activeState]);

    const setActiveHeading = (id) => {
        setActiveState(id);
    };

    let oneClasses = classNames(classes.heading, {
        [classes.activeHeading]: activeState === 'one',
    });
    let twoClasses = classNames(classes.heading, {
        [classes.activeHeading]: activeState === 'two',
    });
    let threeClasses = classNames(classes.heading, {
        [classes.activeHeading]: activeState === 'three',
    });

    const checkAndScroll = (id) => {

        console.log(refOne.current) // comes back undefined

        if (id === 'one' && !inViewOne) {
            scrollToRef(refOne);
        } else if (id === 'two' && !inViewTwo) {
            scrollToRef(refTwo);
        } else if (id === 'three' && !inViewThree) {
            scrollToRef(refThree);
        }
    };
    const scrollToRef = (ref) => {

        console.log(refOne.current) // comes back undefined

        if (ref && ref.current) {
            ref.current.scrollIntoView();
        }
    };

    return (
        <>
            <div className={classes.headingsContainer}>
                <h3
                    className={oneClasses}
                    id={classes.headingOne}
                    onClick={() => setActiveHeading('one')}
                >
                    One
                </h3>
                <h3
                    className={twoClasses}
                    id={classes.headingTwo}
                    onClick={() => setActiveHeading('two')}
                >
                    Two
                </h3>
                <h3
                    className={threeClasses}
                    id={classes.headingThree}
                    onClick={() => setActiveHeading('three')}
                >
                    Three
                </h3>
            </div>
            <div className={classes.container}>
                <div ref={refOne} className={classes.one} />
                <div ref={refTwo} className={classes.two} />
                <div ref={refThree} className={classes.three} />
            </div>
        </>
    );
};

export default Projects;

我已经为此工作了好几个小时,但我已经筋疲力尽了。非常感谢任何帮助!

【问题讨论】:

  • 有点好奇,你试过useEffect而不是useLayoutEffect吗?

标签: javascript reactjs react-hooks ref react-intersection-observer


【解决方案1】:

我在这里明确使用useLayoutEffect 来等待所有 DOM 节点被完全绘制。

useLayoutEffect 中安排的更新将被同步刷新,在浏览器有机会绘制之前

React docs 说这个关于 useLayoutEffect

您是否尝试过useEffect 而不是useLayoutEffect

【讨论】:

  • 是的,我是从useEffect开始的,但是由于它不起作用,所以我切换到了useLayoutEffect。无论如何,我发现了手头的问题,并将发布正确的回复。感谢您的意见!
  • 酷。库react-intersection-observer 中的命名约定是令人困惑/误导的。感谢您的回答顺便说一句。
【解决方案2】:

我终于想通了,这太愚蠢了。

react-intersection-observer 钩子提供了一个 ref、一个 inView 布尔值和一个入口对象。但是,ref 实际上并不是 ref。

ref 是一个回调函数,它不包含当前属性(因此是未定义的)。在此处查看创建者的评论:https://github.com/thebuilder/react-intersection-observer/issues/285#issuecomment-572980628

您应该做的是使用它返回的条目对象,并访问目标属性。如果您正确分配了引用,entry.target 将包含您分配引用的 html 节点。

【讨论】:

    猜你喜欢
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2021-08-07
    • 2017-04-05
    相关资源
    最近更新 更多