簡體   English   中英

如何在React Router中生成動態路由?

[英]How to generate dynamic routes in react router?

我正在嘗試創建房屋列表,單擊時每個房屋都將指向帶有該房屋數據的單獨頁面。 當前,所有數據都是我在構造函數中創建的靜態數據,名為leaseData 我希望Route path指向/dashboard/lease-id 我試圖將地址和monthlyRent都傳遞到Lease組件中,以便可以在新組件中呈現該數據。 我該怎么做呢?

import React, { Component } from 'react'
import { Link, Route } from 'react-router-dom'
import { Lease } from './Lease'

class Dashboard extends Component {
  constructor(props) {
    super(props)
    this.match = this.props.match

    this.leaseData = [
      {
        id: 1,
        address: '18291 Rainbow Dr, Cool Springs CA 93102',
        monthlyRent: 4300
      },
      {
        id: 2,
        address: '2200 Stiller Dr, Las Vegas NV 96274',
        monthlyRent: 1500
      },
      {
        id: 3,
        address: '21626 Sleepy Hollow Ct, Walnut CA 91763',
        monthlyRent: 2400
      }
    ]
  }

  render() {

    let linkList = this.leaseData.map(lease => {
      return (
        <li>
          <Link to={`${this.match.url}/${lease.id}`}>
          <img src="https://cdn.edinarealty.com/media/2256/homepage-tiles_new-construction.jpg" alt="HTML5 Icon"></img>
          </Link>
        </li>
      )
    })

    return (
      <div>
        MAIN DASHBOARD
        <ul>
         <li> {linkList} </li>
        </ul>
        <Route path={`${this.match.url}/:lease-id`} render={<Lease data={}/>}/>
      </div>
    )
  }
}

讓我們嘗試分離App和Dashboard邏輯,以便我們可以更清晰地呈現事物。

這是一個供參考的沙箱: https : //codesandbox.io/s/suspicious-merkle-4bxv3

App.js

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route } from "react-router-dom";
import Dashboard from "./Dashboard";
import Lease from "./Lease";

import "./styles.css";

class App extends React.Component {
  state = {
    leaseData: [
      {
        id: 1,
        address: "18291 Rainbow Dr, Cool Springs CA 93102",
        monthlyRent: 4300
      },
      {
        id: 2,
        address: "2200 Stiller Dr, Las Vegas NV 96274",
        monthlyRent: 1500
      },
      {
        id: 3,
        address: "21626 Sleepy Hollow Ct, Walnut CA 91763",
        monthlyRent: 2400
      }
    ],
    selected: null
  };

  changeSelected = id => {
    this.setState({
      selected: this.state.leaseData.find(lease => lease.id == id)
    });
  };

  render() {
    return (
      <BrowserRouter>
        <Route
          path="/"
          exact
          render={props => <Dashboard data={this.state.leaseData} />}
        />
        <Route
          path="/lease/:id"
          render={props => (
            <Lease
              {...props}
              selected={this.state.selected}
              changeSelected={this.changeSelected}
            />
          )}
        />
      </BrowserRouter>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Dashboard.js

import React, { Component } from "react";
import { Link } from "react-router-dom";

class Dashboard extends Component {
  render() {
    let linkList = this.props.data.map((lease, index) => {
      return (
        <li key={index}>
          <Link to={`/lease/${lease.id}`}>
            <img
              src="https://cdn.edinarealty.com/media/2256/homepage-tiles_new-construction.jpg"
              alt="HTML5 Icon"
            />
          </Link>
        </li>
      );
    });

    return (
      <div>
        MAIN DASHBOARD
        <ul>{linkList}</ul>
      </div>
    );
  }
}

導出默認儀表板;

Lease.js

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

const Lease = props => {
  useEffect(() => {
    const id = props.match.params.id;
    props.changeSelected(id);
  }, []);

  const { selected } = props;

  if (!selected) {
    return <div>Loading...</div>;
  } else {
    return (
      <div>
        <Link to="/">Back to home</Link>
        <h4>Id: {selected.id}</h4>
        <h4>Address: {selected.address}</h4>
        <h4>Rent: {selected.monthlyRent}</h4>
      </div>
    );
  }
};

export default Lease;

主要說明:

  1. App.js包含我們的路由器,租約數據和選定的租約。
  2. 通過使用render道具,我們可以將數據從App狀態傳遞到Route的組件。 對於Dashboard Route,我們傳遞了整個lease-data 對於“租賃”路線,我們傳入changeSelected()來幫助檢索選定的租賃項目,並selected找到的租賃項目。 另外,我們散布了{... props}來獲取matchhistory等道具。
  3. 在儀表板中,我們使用您設置的相同列表生成邏輯來顯示項目。
  4. 當您單擊圖像並重定向到Lease組件時,我們將啟動changeSelected函數。 這發生在useEffect() ,我們使用props.match.params.id來獲取通過Link導航到的租約的ID(也在URL中)。
  5. 將該值傳遞給changeSelected(),它將使用列表中指定的租賃對象更新App狀態中的selected值。
  6. App.js被重新渲染(由於狀態更改),並將selected項目狀態值向下傳遞給Lease ,我們將使用它來顯示有關該租賃對象的信息。

總的來說,在集成redux之前,這樣做是一種干凈的方法。

您可以使用路由器交換機來生成租用路由,如下所示:

import React, { Component } from 'react'
import { Switch, Link, Route } from 'react-router-dom'
import { Lease } from './Lease'

class Dashboard extends Component {
  constructor(props) {
    super(props)
    this.match = this.props.match

    this.leaseData = [
      {
        id: 1,
        address: '18291 Rainbow Dr, Cool Springs CA 93102',
        monthlyRent: 4300
      },
      {
        id: 2,
        address: '2200 Stiller Dr, Las Vegas NV 96274',
        monthlyRent: 1500
      },
      {
        id: 3,
        address: '21626 Sleepy Hollow Ct, Walnut CA 91763',
        monthlyRent: 2400
      }
    ]
  }

  render() {

    let linkList = this.leaseData.map(lease => {
      return (
        <li>
          <Link to={`${this.match.url}/${lease.id}`}>
          <img src="https://cdn.edinarealty.com/media/2256/homepage-tiles_new-construction.jpg" alt="HTML5 Icon"></img>
          </Link>
        </li>
      )
    })

    let leaseRoutes = this.leaseData.map(lease => <Route exact path={`${this.match.url}/${lease.id}`} render={<Lease data={lease}/>}/>)

    return (
      <div>
        MAIN DASHBOARD
        <ul>
         <li> {linkList} </li>
        </ul>
        <Switch>
            {leaseRoutes}
        </Switch>
        <Route path={`${this.match.url}/:lease-id`} render={<Lease data={}/>}/>
      </div>
    )
  }
}

砂箱

Dashboard提取數據,這將使我們能夠在裝入Lease組件時按id查找數據

您可以在實現后端時將其替換為api調用

const data = [
  {
    id: 1,
    address: "18291 Rainbow Dr, Cool Springs CA 93102",
    monthlyRent: 4300
  },
  {
    id: 2,
    address: "2200 Stiller Dr, Las Vegas NV 96274",
    monthlyRent: 1500
  },
  {
    id: 3,
    address: "21626 Sleepy Hollow Ct, Walnut CA 91763",
    monthlyRent: 2400
  }
];

match.params.leaseId提取match.params.leaseId並在使用useEffect並以leaseId作為依賴項進行組件安裝時進行useEffect

當你有API准備只需更換data.find用的API調用leaseId

之所以要在安裝時查找它,是因為它將使我們能夠直接訪問URL,而無需通過儀表板來加載數據。

const Lease = ({
  match: {
    params: { leaseId }
  }
}) => {
  const [leaseData, setLeaseData] = useState(null);

  useEffect(() => {
    setLeaseData(data.find(d => d.id.toString() === leaseId));
  }, [leaseId]);

  if (!leaseData) return null;

  return (
    <div>
      <h1>{leaseData.id}</h1>
      <p>{leaseData.address}</p>
      <p>{leaseData.monthlyRent}</p>
    </div>
  );
};

當網址/dashboard使用道具渲染生成主Dashboard ,並創建一個Route路徑leaseId

const Dashboard = ({ match: { url } }) => {
  const linkList = data.map(lease => {
    return (
      <li key={lease.id}>
        <Link to={`${url}/${lease.id}`}>
          <img
            src="https://cdn.edinarealty.com/media/2256/homepage-tiles_new-construction.jpg"
            alt="HTML5 Icon"
          />
        </Link>
      </li>
    );
  });

  return (
    <Switch>
      <Route
        exact
        path={url}
        render={() => (
          <div>
            MAIN DASHBOARD
            <ul>{linkList}</ul>
          </div>
        )}
      />
      <Route path={`${url}/:leaseId`} component={Lease} />
    </Switch>
  );
};

const Home = () => (
  <div>
    <Link to="/dashboard">Dashboard</Link>
  </div>
);

const App = () => (
  <Router>
    <Switch>
      <Route exact path="/" component={Home} />
      <Route path="/dashboard" component={Dashboard} />
    </Switch>
  </Router>
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM