React: Redirect-реакции-router-dom не перезагружает страницу, а меняет URL - PullRequest
0 голосов
/ 21 апреля 2020

Я пытаюсь перенаправить страницы, используя <Redirect> в react-router-dom. Единственная проблема заключается в том, что он изменяет URL-адрес, но не перезагружает страницу, как это должно быть.

Приложение. js

import React from "react";
import "./Style.css";
import Gallery from "./components/layout/Gallery";
import Preview from "./components/layout/Preview";
import Header from "./components/layout/Header";
import { HashRouter as Router, Switch, Route } from "react-router-dom";

function App() {
  return (
    <Router>
      <>
        <Header />
        <Switch>
          <Route path="/" exact component={Gallery} />
          <Route path="/:id" component={Preview} /> /////////THIS IS WHAT I'M FOCUSING AT (Preview)///////
        </Switch>
        <footer>
          <span className="footer-text">Made by Luis 2020&copy;</span>
        </footer>
      </>
    </Router>
  );
}

export default App;

Предварительный просмотр. js

import React, { useState, useEffect } from "react";
import { Redirect } from "react-router-dom";

function Preview({ match }) {
  const [imageName, setImageName] = useState();
  const [images, setImages] = useState();
  const [finishedLoading, setFinishedLoading] = useState(false);
  const [nextPage, setNextPage] = useState();
  const [prevPage, setPrevPage] = useState();
  const [toNextPage, setToNextPage] = useState();
  const [toPrevPage, setToPrevPage] = useState();

  function setPages() {
    let currentIndex = 0;
    let nextIndex = 0;
    let prevIndex = 0;

    if (finishedLoading) {
      //Sets current page
      Object.keys(images).map((image, index) => {
        if (image === imageName) currentIndex = index;
      });

      //Sets next page
      nextIndex = currentIndex + 1;

      if (nextIndex > 0) setNextPage(Object.keys(images)[nextIndex]);
      else setNextPage(null);

      //Sets previous page
      prevIndex = currentIndex - 1;

      if (prevIndex > 0) setPrevPage(Object.keys(images)[prevIndex]);
      else setPrevPage(null);
    }
  }

  function importAll(r) {
    let images_ = {};

    r.keys().map((item, index) => {
      images_[item.replace("./", "")] = r(item);
    });

    setFinishedLoading(true);
    return images_;
  }

  function toTitle(str) {
    return str
      .split(" ")
      .map(function (ele) {
        return ele[0].toUpperCase() + ele.slice(1).toLowerCase();
      })
      .join(" ");
  }

  useEffect(() => {
    setImageName(String(match.params.id));
    setImages(importAll(require.context("../images", false, /\.jpg/)));
  }, []);

  useEffect(() => {
    if (finishedLoading) setPages();
  }, [finishedLoading, imageName]);

  useEffect(() => {
    setToNextPage(false);
  }, [toNextPage]);

  useEffect(() => {
    setToPrevPage(false);
  }, [toPrevPage]);

  return (
    <>
      {toNextPage ? <Redirect to={`/${nextPage}`} /> : null} ////////IMPORTANT
      {toPrevPage ? <Redirect to={`/${prevPage}`} /> : null} ////////IMPORTANT

      {images === undefined || images === null ? (
        <img
          className="loading"
          key="loading"
          src={loading}
          alt="Loading..."
          width="100"
        />
      ) : (
        <>
          <h2 className="preview-title">
            {toTitle(imageName.replace(".jpg", "").replace(/-/g, " "))}
          </h2>
          <div className="preview">
            <img
              src={images[imageName]}
              alt={String(imageName)}
              key={String(imageName)}
              width="400"
            />
          </div>
          <div className="nav-buttons">
            <button onClick={() => setToNextPage(true)}>&lt;</button> ////IMPORTANT
            <button onClick={() => setToPrevPage(true)}>&gt;</button> ////IMPORTANT
          </div>
        </>
      )}
    </>
  );
}

export default Preview;

1 Ответ

1 голос
/ 21 апреля 2020

Проблема в вашем коде заключается в том, что вы используете Redirect для фактического изменения страницы, которая просто меняет параметры маршрута. Здесь происходит то, что в таком случае компонент Preview не перемонтируется, а перерисовывается с другими параметрами соответствия.

В таком случае ваш компонент будет продолжать перенаправление, так как значения toNextPage и toPrevPage не сбрасываются.

Также у вас есть следующий код useEffect

useEffect(() => {
    setImageName(String(match.params.id));
    setImages(importAll(require.context("../images", false, /\.jpg/)));
  }, []);

Так как он имеет пустую зависимость, он не выполняется при изменении параметров

В целом Вы можете улучшить этот код выше используя вместо этого history.pu sh или перенаправьте

import React, { useState, useEffect } from "react";
import { Redirect } from "react-router-dom";

function Preview({ match }) {
  const [imageName, setImageName] = useState();
  const [images, setImages] = useState();
  const [finishedLoading, setFinishedLoading] = useState(false);
  const [nextPage, setNextPage] = useState();
  const [prevPage, setPrevPage] = useState();

  function setPages() {
    let currentIndex = 0;
    let nextIndex = 0;
    let prevIndex = 0;

    if (finishedLoading) {
      //Sets current page
      Object.keys(images).map((image, index) => {
        if (image === imageName) currentIndex = index;
      });

      //Sets next page
      nextIndex = currentIndex + 1;

      if (nextIndex > 0) setNextPage(Object.keys(images)[nextIndex]);
      else setNextPage(null);

      //Sets previous page
      prevIndex = currentIndex - 1;

      if (prevIndex > 0) setPrevPage(Object.keys(images)[prevIndex]);
      else setPrevPage(null);
    }
  }

  function importAll(r) {
    let images_ = {};

    r.keys().map((item, index) => {
      images_[item.replace("./", "")] = r(item);
    });

    setFinishedLoading(true);
    return images_;
  }

  function toTitle(str) {
    return str
      .split(" ")
      .map(function (ele) {
        return ele[0].toUpperCase() + ele.slice(1).toLowerCase();
      })
      .join(" ");
  }

  useEffect(() => {
    setImageName(String(match.params.id));
    setImages(importAll(require.context("../images", false, /\.jpg/)));
  }, [match.params.id]);

  useEffect(() => {
    if (finishedLoading) setPages();
  }, [finishedLoading, imageName]);

  const changePage = (page) => {
    history.push(`/${page}`);
  } 

  return (
    <>

      {images === undefined || images === null ? (
        <img
          className="loading"
          key="loading"
          src={loading}
          alt="Loading..."
          width="100"
        />
      ) : (
        <>
          <h2 className="preview-title">
            {toTitle(imageName.replace(".jpg", "").replace(/-/g, " "))}
          </h2>
          <div className="preview">
            <img
              src={images[imageName]}
              alt={String(imageName)}
              key={String(imageName)}
              width="400"
            />
          </div>
          <div className="nav-buttons">
            <button onClick={() => changePage(nextPage)}>&lt;</button> ////IMPORTANT
            <button onClick={() => changePage(prevPage)}>&gt;</button> ////IMPORTANT
          </div>
        </>
      )}
    </>
  );
}

export default Preview;
...