javascript - 如何使用 useInView 钩子(Hook)识别 React 组件并将其值传递给子组件?

标签 javascript reactjs react-hooks

我正在使用 React 创建一个导航栏,当用户将其滚动到 View 中时,该导航栏会在视觉上突出显示事件组件。因此,他们滚动到“关于”组件,用户图标将突出显示,主页图标将恢复正常。它看起来像这样:

enter image description here

我尝试分两步完成此操作:(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 个问题:

  1. 我需要为每个被观察的元素一个单独的 useInView 钩子(Hook)。
  2. 在组件调用上使用“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/

相关文章:

javascript - 测试嵌套的 React 组件

javascript - React useState 钩子(Hook)变量的破坏性排序?

javascript - 与 useEffect 一起使用时如何防止 useCallback 触发(并遵守 eslint-plugin-react-hooks)?

javascript - 执行动态加载的JS文件

javascript - 使用 Ajax/Javascript 增加 Rails 模型列

javascript - 在 CircleCI 上的 Nightwatch 测试期间选择要上传的文件(图像)

javascript - 为什么异步函数中的连续 setState 调用不进行批处理?

javascript - 将 DIV 居中放置在 DIV 中

reactjs - IndexRoute 未显示在路线内

reactjs - React - 带有异步 setState 的 useEffect 导致额外的重新渲染