我正在尝试为项目上的水平滚动部分实现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;
我已经为此工作了几个小时,现在我机智已尽。任何帮助深表感谢!
答案 0 :(得分:0)
useLayoutEffect
等待所有DOM节点被完全绘制。在
useLayoutEffect
内计划的更新将被同步刷新,在浏览器有机会绘制之前。
反应docs谈到useLayoutEffect
。
您尝试使用useEffect
而不是useLayoutEffect
吗?
答案 1 :(得分:0)
我终于弄明白了,这真是愚蠢。
react-intersection-observer挂钩提供了ref,inView布尔值和入口对象。但是,参考实际上不是参考。
ref是一个回调函数,其中不包含当前属性(因此未定义)。在此处查看创建者的评论:https://github.com/thebuilder/react-intersection-observer/issues/285#issuecomment-572980628
您应该做的是使用返回的入口对象,并访问target属性。如果您已正确分配引用,则 entry.target 将包含您将引用分配给的html节点。