有没有办法使用 React Router 重定向到默认的 url 哈希?

Posted

技术标签:

【中文标题】有没有办法使用 React Router 重定向到默认的 url 哈希?【英文标题】:Is there a way to redirect to a default url hash with React Router? 【发布时间】:2020-02-03 18:52:37 【问题描述】:

我正在使用 React Router 5。

我有一个路径/item/:id。当我导航到此路径时,我希望能够使用默认哈希标识符加载页面。 i.e. /item/:id#123

有关更多上下文,我的页面上有一个与项目相关联的步骤列表。每次用户选择不同的步骤时,哈希值都会相应更改,如下所示:

step 1 -> /item/123#1
step 2 -> /item/123#2
step 3 -> /item/123#3

这是我的组件代码的粗略实现:

import  withRouter  from 'react-router-dom'
import steps from './steps'

const ItemPage = ( history, location ) => 
  const  hash, pathname  = location
  const changeURLhash = idx => 
    history.push( pathname: pathname, hash: idx.toString() )
  

  return (
    <ul>
      steps.map(step => (
        <li key=i onClick=changeURLhash>
          step.title
        </li>
      ))
    </ul>
  )

我可以在选择一个步骤后更改哈希值,但在初始页面加载时没有点击任何内容但 url 路径中没有哈希值。我需要更改此设置,因为在页面加载时默认选择第 1 步。

最好的方法是什么?提前致谢!

【问题讨论】:

我假设这是针对用户在表单上完成某些内容,然后离开然后回来的场景,您希望将进度保存一些正确的方式吗? @ChristopherNgo 没错。用户应该能够在不同的浏览器上复制和粘贴该链接,并显示当前处于活动状态的步骤的相同状态。只需要初始默认哈希选择。 我明白了。但是在这种情况下,如何保留前面步骤中的数据呢? @ChristopherNgo 我明白你的意思。步骤的状态作为保存数据的用户类型被持久化。但我使用哈希标识符跟踪的唯一内容是突出显示了哪一步。 【参考方案1】:

我已经能够通过在 useEffect 挂钩中使用 history.replace 来解决这个问题。

当页面加载并且 url 中没有哈希标识符时,我将历史堆栈中的当前路径替换为包含默认哈希的新路径

useEffect(() => 
  if (!hash) history.replace( pathname: pathname, hash: '0' )
, [hash, history, pathname])

在这里使用替换而不是推送消除了添加到历史堆栈中的不必要的额外条目。

【讨论】:

能否详细说明您使用的是window.history 还是let history = useHistory()【参考方案2】:

如果无法查看您的代码,就很难为您的问题提供准确的解决方案。但是,我已经为您创建了一个沙盒来演示如何执行此操作。

https://codesandbox.io/s/gifted-sinoussi-5eomb

基本上,您的Item 组件需要useStateuseEffect 的组合

import React,  useState, useEffect  from "react";

const Item = ( steps ) => 
  const [currentStep, setCurrentStep] = useState(1);

  useEffect(() => 
    const path = window.location.href;
    const step =
      path.indexOf("#") !== -1 ? path.slice(path.indexOf("#") + 1) : "";
    if (step) 
      setCurrentStep(step);
    
  , []);

  const handleOnClick = step => 
    setCurrentStep(step);
  ;

  const createSteps = () => 
    return steps.map((step, index) => 
      return (
        <div
          className=step == currentStep ? "currentStep" : "step"
          key=index
          onClick=() => handleOnClick(step)
        >
          <h4>Step: step</h4>
          <input />
        </div>
      );
    );
  ;
  return <div>createSteps()</div>;
;

export default Item;

您有一个状态来跟踪当前步骤。还有一个标记创建器功能,用于将突出显示的类应用于活动项目。然后在useEffect() 中,您只需提取步骤编号(# 之后的字符)并将您的状态设置为该值。这将重新渲染组件,并且您的标记创建者会将类应用于该步骤。

【讨论】:

我试过这样做,但问题是 url 在组件挂载后附加哈希,并在历史堆栈中创建不必要的额外条目。所以一开始 url 看起来像 /item/123,然后过了一会儿它变成 /item/123#0。要返回,用户必须单击两次。希望这是有道理的。寻找一种更优化的方式来在首次访问时设置默认 #0。

以上是关于有没有办法使用 React Router 重定向到默认的 url 哈希?的主要内容,如果未能解决你的问题,请参考以下文章

重定向到 https 安全在 react-router 中不起作用

react-router-v4 没有正确重定向

如何使用 React Router 的重定向功能?

如何使用 react-router 重定向到另一条路由?

React Router 将 IndexRoute 重定向到正确的路径

如何从 express 重定向到 react-router?