我正在使用 React 创建一个导航栏,当用户将其滚动到 View 中时,该导航栏会在视觉上突出显示事件组件。因此,他们滚动到“关于”组件,用户图标将突出显示,主页图标将恢复正常。它看起来像这样:
我尝试分两步完成此操作:(1) 在我的 App.jsx 组件中使用 useInView Hook ,当用户滚动到 useInView {ref} 时使用 useState Hook 设置“activeElement”,并且(2 ) 通过 props 和 useEffect 将“activeElement”作为 useState 变量传递给子 Nav 组件,以便在用户滚动时更新 Nav 组件中的 activeNav。
这是我的应用程序组件代码,我一直在段落标签中对其进行测试。目前,activeElement 不受滚动影响。
const App = () => {
const { ref, inView, entry } = useInView({
/* Optional options */
threshold: 0,
});
const [activeElement, setActiveElement] = useState('#')
return (
<>
<Header ref={ref} setActiveElement={inView ? '#home' : '' }/>
<Nav activeElement={activeElement}/>
<About ref={ref} setActiveElement={inView ? '#about' : '' } />
<p>{activeElement}</p>
<Services ref={ref} setActiveElement={inView ? '#services' : '' } />
<Contact ref={ref} setActiveElement={inView ? '#contact' : '' }/>
<Footer />
<p>{activeElement}</p>
</>
)
}
export default App
这是我的导航组件的代码:
const Nav = ({activeElement}) => {
const [activeNav, setActiveNav] = useState('#');
useEffect(() => {
setActiveNav(activeElement);
})
return (
<nav>
<a href="#" onClick={() => setActiveNav('#')} className={activeNav === '#' ? 'active' : ''}><AiOutlineHome /></a>
<a href="#about" onClick={() => setActiveNav('#about')} className={activeNav === '#about' ? 'active' : ''}><AiOutlineUser /></a>
<a href="#experience" onClick={() => setActiveNav('#experience')} className={activeNav === '#experience' ? 'active' : ''}><HiOutlineBookOpen /></a>
<a href="#services" onClick={() => setActiveNav('#services')} className={activeNav === '#services' ? 'active' : ''}><FaUncharted /></a>
<a href="#contact" onClick={() => setActiveNav('#contact')} className={activeNav === '#contact' ? 'active' : ''}><RiMessage2Line /></a>
</nav>
)
}
export default Nav
我的 useInView 执行有什么问题?我是否正确地将 activeElement 变量传递给 Nav 组件?
感谢您花时间阅读本文。
最佳答案
** 解决方案: **
经过一番挖掘,并感谢评论者 Ali Mirzaei 帮助确定问题发生的位置,我们发现了 2 个问题:
- 我需要为每个被观察的元素一个单独的 useInView 钩子(Hook)。
- 在组件调用上使用“ref”会产生错误:“警告:无法为函数组件提供引用。尝试访问此引用将失败。”所以,我使用了https://stackoverflow.com/a/65756885/13471663中的答案将 ref 作为名为 innerRef 的 prop 传递
工作代码如下:
const App = () => {
const { ref, inView } = useInView();
const { ref: ref1, inView: inView1 } = useInView();
const { ref: ref2, inView: inView2 } = useInView();
const { ref: ref3, inView: inView3 } = useInView();
const { ref: ref4, inView: inView4 } = useInView();
const [activeElement, setActiveElement] = useState('#')
useEffect(() => {
if (inView) {
setActiveElement('#home');
console.log('home');
};
if (inView1) {
setActiveElement('#about')
console.log('about');
};
if (inView2) {
setActiveElement('#experience')
console.log('experience');
};
if (inView3) {
setActiveElement('#services')
console.log('services');
};
if (inView4) {
setActiveElement('#contact')
console.log('contact');
};
}, [inView, inView1, inView2, inView3, inView4])
return (
<>
<Header innerRef={ref} />
<Nav activeElement={activeElement}/>
<About innerRef={ref1} />
<p>{activeElement} {inView.toString()}</p>
<Experience innerRef={ref2} />
<Services innerRef={ref3} />
<Contact innerRef={ref4} />
<Footer />
<p>{activeElement}</p>
</>
)
}
export default App
对于导航组件:
const Nav = ({activeElement}) => {
const [activeNav, setActiveNav] = useState('#home');
useEffect(() => {
setActiveNav(activeElement);
})
return (
<nav>
<a href="#" onClick={() => setActiveNav('#home')} className={activeNav === '#home' ? 'active' : ''}><AiOutlineHome /></a>
<a href="#about" onClick={() => setActiveNav('#about')} className={activeNav === '#about' ? 'active' : ''}><AiOutlineUser /></a>
<a href="#experience" onClick={() => setActiveNav('#experience')} className={activeNav === '#experience' ? 'active' : ''}><HiOutlineBookOpen /></a>
<a href="#services" onClick={() => setActiveNav('#services')} className={activeNav === '#services' ? 'active' : ''}><FaUncharted /></a>
<a href="#contact" onClick={() => setActiveNav('#contact')} className={activeNav === '#contact' ? 'active' : ''}><RiMessage2Line /></a>
</nav>
)
}
export default Nav
下面是组件使用 insideRef 的示例:
const About = ({ innerRef }) => {
return (
<section id='about'>
<div ref={innerRef}>
About
</div>
</section>
)
}
希望对遇到同样问题的人有所帮助!
关于javascript - 如何使用 useInView 钩子(Hook)识别 React 组件并将其值传递给子组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72443582/