【问题标题】:Scroll onClick using React.fowardRef is not working使用 React.fowardRef 滚动 onClick 不起作用
【发布时间】:2020-10-08 14:13:39
【问题描述】:

我想知道如何使用 React refs 导航到特定组件

function App() {
  let CompetencesRef = React.createRef();
  let ExperiencesRef = React.createRef();
  let FormationRef = React.createRef();
  let RecoRef = React.createRef();
  let refs = { CompetencesRef, ExperiencesRef, FormationRef, RecoRef }
  let scrollToRef = (reference) => {
    console.log(reference)
    reference.current.scrollIntoView({ behavior: 'smooth' })
  }
  return (
    <ParallaxProvider>
      <ThemeProvider theme={theme}>
        <div className="App">

          <div className="hero">
            <HeaderApp refs={refs} scrollToRef={scrollToRef} />
            <ApprochApp />
          </div>
          <Apropos />
          <Competences ref={CompetencesRef} />
          <Experiences ref={ExperiencesRef} />
          <Formation ref={FormationRef} />
          <Recom ref={RecoRef} />
          <Contact />
          <Footer />

        </div >
      </ThemeProvider>
    </ParallaxProvider>
  );
}

export default App;

AppHeader

const AppHeader = (props, refs, scrollToRef) => {
    console.log(props)

    return (
        <div >
            <Headroom>
                <MenuApp refs={props.refs} scrollToRef={props.scrollToRef} />
            </Headroom>

        </div>

    )
}
export default AppHeader

AppMenu

const MenuApp = (props, refs, scrollToRef) => {
    console.log(props)
    return (
        <div className="menu sticky-inner grid-container">
            <div className="desktop-menu">
                <div className="menu-item a-propos" ref={props.refs.CompetencesRef} onClick={() => props.scrollToRef(props.refs.CompetencesRef)}>
                    <p className='button'>Compétences</p>
                </div>
                <div className="menu-item competences" ref={props.refs.ExperiencesRef} onClick={() => props.scrollToRef(props.refs.ExperiencesRef)} >
                    <p className='button'>Experiences </p>
                </div>
                <div className="menu-item experiences" ref={props.refs.FormationRef} onClick={() => props.scrollToRef(props.refs.FormationRef)}>
                    <p className='button'>Formation</p>
                </div>
                <div className="menu-item formation" ref={props.refs.RecoRef} onClick={() => props.scrollToRef(props.refs.RecoRef)}>
                    <p className='button'>Recomendations </p>
                </div>
            </div>
            <p className="mobile-menu">
                <MenuIcon />
            </p>
            <div className="github-ico">
                <GitHubIcon />
            </div>
            <div className="linkedin-ico">
                <LinkedInIcon />
            </div>
            <div className="contact">
                <div className='contact-btn'>
                    <span className="contact-ico"> <MessageIcon /></span>  <span style={isBrowser ? { display: 'block' } : { display: 'none' }} > contact </span>
                </div>
            </div>
        </div>
    )
}
export default React.forwardRef(MenuApp) 

我在 Apps.js 中使用带有 scrollIntoView 的 ClickHandler。但实际上当我点击视图时不会滚动。

我不会使用像 react-scroll 这样的包

【问题讨论】:

  • forwardRef 在哪里?例如,您如何将 ref 传递给Competences,请制作一个可重现的示例How to create a Minimal, Reproducible Example
  • 哦,我明白了,forwardRef 不是这样工作的,请参阅文档
  • 我想我像这个例子一样使用它gist.github.com/jamesreggio/142215754ad06f375bd87657c6227ed8
  • 请做一个普通的沙箱,我不明白这段代码的结构,AppHeaderMenuApp是从哪里来的?例如,您如何将 ref 传递给 Competences
  • 你可以在 App.js 中看到它们来自哪里。我有嵌套组件

标签: javascript reactjs react-ref js-scrollintoview


【解决方案1】:

这是一个最小的可重现示例(没有所有代码噪音):

function App() {
  const competencesRef = React.useRef();
  const refs = { competencesRef /* ExperiencesRef, FormationRef, RecoRef */ };
  const scrollToRef = (reference) => {
    reference.current.scrollIntoView({ behavior: "smooth" });
  };
  return (
    <>
      <AppHeader refs={refs} scrollToRef={scrollToRef} />
      <Competences ref={competencesRef} />
    </>
  );
}

const Competences = React.forwardRef((props, ref) => {
  return <div ref={ref}>...</div>;
});

const AppHeader = (props) => {
  return <MenuApp refs={props.refs} scrollToRef={props.scrollToRef} />;
};

const MenuApp = (props) => {
  return (
    <div
      ref={props.refs.competencesRef}
      onClick={() => props.scrollToRef(props.refs.competencesRef)}
    >
      <p className="button">Compétences</p>
    </div>
  );
};

您的代码的问题是您使用React.createRef 而不是React.useRef(您可以搜索差异),并且您需要React.forwardRef 仅用于使用ref 属性的组件,例如Competences

【讨论】:

  • 很好,我错过了那个!
【解决方案2】:

你的代码有两个问题:

首先,函数组件和类组件使用ref是有区别的。在功能组件上使用ref 会产生意想不到的结果,因为它们是don't have an instance

您应该对所有部分组件使用forwardRef,并确保将ref 放置在包装元素上。

第二个问题是您将 refs 用于两个组件。 Refs 应该只分配给单个组件(可能并非在所有情况下)。在这种情况下,您需要对部分组件的引用来获取 HTML 元素。

所以删除 AppMenu 组件中的 ref 属性:

<div className="menu-item a-propos" onClick={() => props.scrollToRef(props.refs.CompetencesRef)}>
  <p className='button'>Compétences</p>
</div>

虽然它可以与 refs 一起使用,但您可能正在考虑更简单的设置。例如。通过使用 id。

如果您确实想继续使用 refs,我还建议您不要将 refs 对象传递给子组件。您实际上不希望子组件“知道”树中更高的组件。

例如,您可以通过处理 App 组件中的 onClick 回调来缓解这种情况。

【讨论】:

    【解决方案3】:

    在你的 scrollToRef 函数中试试这个:

    window.scrollTo(0, reference.current.offsetTop);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      • 2022-06-23
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多