我正在尝试为项目上的水平滚动部分实现POC。我在水平滚动部分上方有3个h3,它们应该对应于水平位中的各个子部分。
我使用react intersection observer来创建子部分的引用,以便在用户点击其中一个h3时能够滚动到它们。状态设置正确,在React Dev Tools中,我可以看到useInView挂钩设置正确,并将s显示为ref。然而,当我尝试在任何地方访问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;
我已经为此工作了好几个小时了,我已经无计可施了。非常感谢您的帮助!
我终于想通了,这太愚蠢了。
react intersection observer钩子提供了一个ref、一个inView布尔值和一个entry对象。然而,引用实际上不是引用。
ref是一个回调函数,它不包含当前属性(因此未定义(。点击此处查看创建者的评论:https://github.com/thebuilder/react-intersection-observer/issues/285#issuecomment-572980628
相反,您应该使用它返回的入口对象,并访问目标属性。如果您正确分配了参考,entry.target将包含您分配参考的html节点。
我在这里显式地使用useLayoutEffect
来等待所有DOM节点被完全绘制
在浏览器有机会绘制之前,
useLayoutEffect
内计划的更新将同步刷新。
React文档中谈到了useLayoutEffect
。
你试过useEffect
而不是useLayoutEffect
吗?