Реагируйте на прокрутку с помощью useRef в отдельных маршрутах - PullRequest
4 голосов
/ 17 апреля 2020

Далее к моему последнему вопросу здесь , я пытался сопоставить ссылки с другими маршрутами. Обработчик прокрутки работает, но ref.current равно null. Поэтому я ищу ответ на эту дилемму. Используя без внешних зависимостей , как я могу решить эту проблему?

App.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;

Home.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;

Вы можете найти ссылку на мою песочницу кода: здесь . Вилы очень ценятся.

1 Ответ

2 голосов
/ 20 апреля 2020

Вы не можете передавать ссылки в качестве реквизитов другим компонентам с именем prop без использования forwardRef для компонента. Вам нужно присвоить ему другое имя, чтобы оно работало, например, innerRefs.

Также для передачи ссылок в качестве реквизита компоненту Route используйте метод render prop

App .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;

Home.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;

Рабочая демонстрация здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...