简体   繁体   中英

React Js - How to change URL when clicking on ant design stepper?

Context:

Using the Ant Design Stepper, I can click on each Step and the Stepper will update and navigate to that step to reflect this. Now I'm trying to add an additional functionality where upon clicking on a Step, the URL also changes. The idea is that the change in URL will route to certain components being displayed on the page. I'm attempting to do this by wrapping the Icon within each Step with Link.

Problem

Now when I click on a Step, the URL does update but the Stepper itself doesn't update and navigate to the Step reflect this. If I click the same Step again then the Stepper will update and navigate to it. I'm hoping to accomplish this without having to click on a Step twice.

Here's the code

<Steps
  size="small"
  current={current}
  onChange={setCurrent}
  type="navigation"
>
  <Steps.Step
    title="People"
    icon={
      <Link to="/workshop/client-portal/stage/file-management/people">
        <Dataset.Icon type="people" />
      </Link>
    }
  />
  <Steps.Step
    title="Positions"
    icon={
      <Link to="/workshop/client-portal/stage/file-management/positions">
        <Dataset.Icon type="positions" />
      </Link>
    }
  />
  <Steps.Step
    title="Links"
    icon={
      <Link to="/workshop/client-portal/stage/file-management/Links">
        <Dataset.Icon type="links" />
      </Link>
    }
  />
  <Steps.Step
    title="Lookups"
    icon={
      <Link to="/workshop/client-portal/stage/file-management/lookups">
        <Dataset.Icon type="lookups" />
      </Link>
    }
  />

Any thoughts or insights would be greatly appreciated.

Thank you for your time.

It seems to me that your issue is due to the fact that you are wrapping only your icons with a link - so clicking the label will not trigger the route change. So basically you can use this pattern in order to link the whole step:

<Steps.Step
    title={
      <Link to="/workshop/client-portal/stage/file-management/people">
        People
      </Link>
    }
    icon={
      <Link to="/workshop/client-portal/stage/file-management/people">
        <Dataset.Icon type="people" />
      </Link>
    }
  />

I created this simplified sandbox based on the code you provided in order to demonstrate how this works.

Another thing you can do, is use the react-router 's history.push() method in order to push to the link you like on the Steps onChange :

<Steps
  size="small"
  current={current}
  onChange={(id)=>{
     setCurrent(id);
     history.push(
     /* the path you want to push to based on the route id */
    )
   }}
  type="navigation"
>

If you go for the second solution you don't even need to use Link s.

Make it simple:

<Steps
  size="small"
  current={current}
  onChange={setCurrent}
  type="navigation"
>
  <Steps.Step
    icon=""
    title={
      <Link to="/workshop/client-portal/stage/file-management/people">
        <Dataset.Icon type="people" /> People
      </Link>
    }
  />
  <Steps.Step
    icon=""
    title={
      <Link to="/workshop/client-portal/stage/file-management/positions">
        <Dataset.Icon type="positions" /> Positions
      </Link>
    }
  />
  <Steps.Step
    icon=""
    title={
      <Link to="/workshop/client-portal/stage/file-management/Links">
        <Dataset.Icon type="links" /> Links
      </Link>
    }
  />
  <Steps.Step
    icon=""
    title={
      <Link to="/workshop/client-portal/stage/file-management/lookups">
        <Dataset.Icon type="lookups" /> Lookups
      </Link>
    }
  />

i think it should works.

You are trying to attach the Link into the icon of Step, it means you can not change the state of Steps by clicking on the description , only icon works.

This is the use query way ( /demo?step=1 ), you can implement another one use hash ( /demo#1 ) your self

import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./styles.css";
import { Steps, Divider } from "antd";
import { BrowserRouter, Route, Link, useLocation } from "react-router-dom";
import { Layout } from "antd";
const { Header } = Layout;
const { Step } = Steps;
function useStep() {
  const params = new URLSearchParams(useLocation().search);
  return parseInt(params.get("step"), 10);
}
const App = () => (
  <BrowserRouter>
    <Header>
      <Link to="/demo">Demo</Link>
    </Header>
    <Route path={"/demo"} component={Demo} />
  </BrowserRouter>
);
const StepContent = () => {
  const step = useStep();
  return <div>This is Step {step}</div>;
};
const Demo = ({ match, history }) => {
  const step = useStep();
  // Init current with step get from the URL 
  // so you can jump to the step 2 by enter the link on the address bar
  const [current, setCurrent] = React.useState(step);
  const onChange = current => {
    setCurrent(current);
    history.push(`${match.path}?step=${current}`);
  };
  return (
    <div style={{ paddingTop: 20 }}>
      <Steps current={current} onChange={onChange}>
        <Step title="Step 0" description="This is a description." />
        <Step title="Step 1" description="This is a description." />
        <Step title="Step 2" description="This is a description." />
      </Steps>
      <Divider />
      <Route path={`${match.path}`} exact component={StepContent} />
    </div>
  );
};
ReactDOM.render(<App />, document.getElementById("root"));

Check the demo on codesandbox :

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM