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

Is there a way to redirect to a default url hash with React Router?

我正在使用 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。

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

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

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;

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

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

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

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

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