React:react-router-dom Redirect 不是重新加载页面,而是更改 URL

Posted

技术标签:

【中文标题】React:react-router-dom Redirect 不是重新加载页面,而是更改 URL【英文标题】:React: react-router-dom's Redirect is not reloading page but changes the URL 【发布时间】:2020-08-04 06:57:09 【问题描述】:

我正在尝试在react-router-dom 中使用<Redirect> 重定向页面。唯一的问题是它会更改 URL,但不会像预期的那样重新加载页面。

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

Preview.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
          
          
        />
      ) : (
        <>
          <h2 className="preview-title">
            toTitle(imageName.replace(".jpg", "").replace(/-/g, " "))
          </h2>
          <div className="preview">
            <img
              src=images[imageName]
              alt=String(imageName)
              key=String(imageName)
              
            />
          </div>
          <div className="nav-buttons">
            <button onClick=() => setToNextPage(true)>&lt;</button> ////IMPORTANT
            <button onClick=() => setToPrevPage(true)>&gt;</button> ////IMPORTANT
          </div>
        </>
      )
    </>
  );


export default Preview;

【问题讨论】:

【参考方案1】:

您的代码中的问题是您使用重定向来实际更改仅更改路由参数的页面。这里发生的情况是,在这种情况下,预览组件不会重新安装,而是使用不同的匹配参数重新渲染。

在这种情况下,您的组件将继续执行重定向,因为 toNextPage 和 toPrevPage 值不会重置。

你还有下面的useEffect代码

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

由于它有一个空依赖,所以当params改变时它不会执行

总体而言,您可以通过改用 history.push 或重定向来改进上述代码

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
          
          
        />
      ) : (
        <>
          <h2 className="preview-title">
            toTitle(imageName.replace(".jpg", "").replace(/-/g, " "))
          </h2>
          <div className="preview">
            <img
              src=images[imageName]
              alt=String(imageName)
              key=String(imageName)
              
            />
          </div>
          <div className="nav-buttons">
            <button onClick=() => changePage(nextPage)>&lt;</button> ////IMPORTANT
            <button onClick=() => changePage(prevPage)>&gt;</button> ////IMPORTANT
          </div>
        </>
      )
    </>
  );


export default Preview;

【讨论】:

谢谢!我会努力做到的:)

以上是关于React:react-router-dom Redirect 不是重新加载页面,而是更改 URL的主要内容,如果未能解决你的问题,请参考以下文章

从cookie异步加载身份验证令牌时,React react-router-dom私有路由不起作用

react-router-dom v5和react-router-dom v6区别

React-router-dom:链接编译失败

`yarn add react-router-dom` 和 `yarn add @types/react-router-dom` 有啥区别?

React:react-router-dom 详解

React使用react-router-dom配置路由