javascript - 在单独的路由中使用 useRef 响应滚动导航

标签 javascript reactjs typescript react-router

继续我的最后一个问题here ,我一直在尝试将引用映射到其他路线。滚动处理程序正在工作,但 ref.currentnull。所以我正在寻找这个困境的答案。 不使用外部依赖项,如何解决此问题?

应用程序.tsx

import React, { useEffect, useRef } from "react";
import { BrowserRouter, Route, NavLink, useLocation } from "react-router-dom";
import Home from "./pages/Home";
import "./styles.css";

const Header = ({ refs }) => {
  const location = useLocation();

  useEffect(() => {
    console.log("location", location.pathname);
    switch (location.pathname) {
      case "/about":
        scrollSmoothHandler(refs.aboutRef);
        break;
      case "/contact":
        scrollSmoothHandler(refs.contactRef);
        break;
      case "/hero":
        scrollSmoothHandler(refs.heroRef);
        break;

      default:
        scrollSmoothHandler(refs.homeRef);
        break;
    }
  }, [location, refs]);

  const scrollSmoothHandler = ref => {
    console.log("Triggered.");
    console.log(ref.current);
    //ref.current.scrollIntoView({ behavior: "smooth" });
  };

  return (
    <>
      <NavLink to="/hero" activeClassName="selected">
        Hero
      </NavLink>
      <NavLink to="/about" activeClassName="selected">
        About
      </NavLink>
      <NavLink to="/contact" activeClassName="selected">
        Contact
      </NavLink>
    </>
  );
};

function App() {
  const homeRef = useRef(null);
  const heroRef = useRef(null);
  const aboutRef = useRef(null);
  const contactRef = useRef(null);

  return (
    <div ref={homeRef} className="App">
      <BrowserRouter>
        <Header refs={{ aboutRef, contactRef, heroRef, homeRef }} />
        <Route
          exact
          to="/"
          refs={{ aboutRef, contactRef, heroRef, homeRef }}
          component={Home}
        />
        // More routes here.
      </BrowserRouter>
    </div>
  );
}

export default App;
<小时/>

首页.tsx

import React, { Fragment, forwardRef, useRef } from "react";
import "../styles.css";

const Hero = forwardRef((props, ref) => {
  return (
    <section ref={ref}>
      <h1>Hero Section</h1>
    </section>
  );
});

const About = forwardRef((props, ref) => {
  return (
    <section ref={ref}>
      <h1>About Section</h1>
    </section>
  );
});

const Contact = forwardRef((props, ref) => {
  return (
    <section ref={ref}>
      <h1>Contact Section</h1>
    </section>
  );
});

function Home(refs) {
  const heroRef = useRef(refs.heroRef);
  const aboutRef = useRef(refs.aboutRef);
  const contactRef = useRef(refs.contactRef);
  return (
    <Fragment>
      <Hero ref={heroRef} />
      <About ref={aboutRef} />
      <Contact ref={contactRef} />
    </Fragment>
  );
}

export default Home;

您可以找到我的代码沙箱的链接:here 。 fork 非常受欢迎。

最佳答案

如果不在组件上使用forwardRef,则无法将 refs 作为 props 传递给具有 name prop 的其他组件。您需要为其指定另一个名称才能使其工作,例如innerRefs。

还要将 refs 作为 prop 传递给 Route 组件,请使用 render prop 方法

应用程序.tsx

import React, { useEffect, useRef } from "react";
import { BrowserRouter, Route, NavLink, useLocation } from "react-router-dom";
import Home from "./pages/Home";
import "./styles.css";

const Header = ({ innerRefs }) => {
  const location = useLocation();

  useEffect(() => {
    console.log("location", location.pathname);
    switch (location.pathname) {
      case "/about":
        scrollSmoothHandler(innerRefs.aboutRef);
        break;
      case "/contact":
        scrollSmoothHandler(innerRefs.contactRef);
        break;
      case "/hero":
        scrollSmoothHandler(innerRefs.heroRef);
        break;

      default:
        scrollSmoothHandler(innerRefs.homeRef);
        break;
    }
  }, [location, innerRefs]);

  const scrollSmoothHandler = innerRef => {
    console.log("Triggered.");
    console.log(innerRef.current);
    innerRef.current.scrollIntoView({ behavior: "smooth" });
  };

  return (
    <>
      <NavLink to="/hero" activeClassName="selected">
        Hero
      </NavLink>
      <NavLink to="/about" activeClassName="selected">
        About
      </NavLink>
      <NavLink to="/contact" activeClassName="selected">
        Contact
      </NavLink>
    </>
  );
};

function App() {
  const homeRef = useRef(null);
  const heroRef = useRef(null);
  const aboutRef = useRef(null);
  const contactRef = useRef(null);

  return (
    <div ref={homeRef} className="App">
      <BrowserRouter>
        <Header innerRefs={{ aboutRef, contactRef, heroRef, homeRef }} />
        <Route
          exact
          to="/"
          render={routeProps => (
            <Home
              {...routeProps}
              innerRefs={{ aboutRef, contactRef, heroRef, homeRef }}
            />
          )}
        />
        // More routes here.
      </BrowserRouter>
    </div>
  );
}

export default App;
<小时/>

首页.tsx

import React, { Fragment, forwardRef, useRef } from "react";
import "../styles.css";

const Hero = forwardRef((props, ref) => {
  return (
    <section ref={ref}>
      <h1>Hero Section</h1>
    </section>
  );
});

const About = forwardRef((props, ref) => {
  return (
    <section ref={ref}>
      <h1>About Section</h1>
    </section>
  );
});

const Contact = forwardRef((props, ref) => {
  return (
    <section ref={ref}>
      <h1>Contact Section</h1>
    </section>
  );
});

function Home({ innerRefs }) {
  return (
    <Fragment>
      <Hero ref={innerRefs.heroRef} />
      <About ref={innerRefs.aboutRef} />
      <Contact ref={innerRefs.contactRef} />
    </Fragment>
  );
}

export default Home;

Working demo here

关于javascript - 在单独的路由中使用 useRef 响应滚动导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61277068/

相关文章:

reactjs - 之前时间和之后时间的统计问题

module - TypeScript 中存在名称冲突时如何解决内部模块

Angular 6 - 行为主题 : get data to stay after refresh

javascript - 动态加载外部 javascript 并将其绑定(bind)到特定的 DOM 元素或命名空间

javascript - 在jsp中的el表达式中使用javascript变量

javascript - Reactjs 将 props 传递给 2 个组件

node.js - typescript : Add a method on a class from another module/Populate a namespace from different modules

javascript - 如何在没有 JSX 的情况下在 React.js 中呈现 html 实体

javascript - 点击展开 FLOT 图

reactjs - 如何为 Paypal 上下文快速结账创建 react 组件?