首页 > 解决方案 > 如何在反应路由器中生成动态路由?

问题描述

我正在尝试创建一个房屋列表,单击后每个房屋将指向一个单独的页面,其中包含该房屋的数据。目前所有数据都是我在构造函数中创建的静态数据 - 命名为leaseData. 我想要Route path指向/dashboard/lease-id。我正在尝试将地址和月租都传递到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>
    )
  }
}

标签: javascriptreactjsreact-router

解决方案


让我们尝试将 App 和 Dashboard 逻辑分开,以便我们可以更清晰地呈现事物。

这是一个沙箱供参考:https ://codesandbox.io/s/suspicious-merkle-4bxv3

应用程序.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);

仪表板.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>
    );
  }
}

导出默认仪表板;

租赁.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. 通过使用renderprop,我们可以将数据从 App-state 传递到Route. 对于 Dashboard Route,我们传入整个lease-data. 对于 Lease 路由,我们传入changeSelected()以帮助检索选定的租约项,selected即找到的项。另外,我们传播 {...props} 来访问像match和之类的道具history
  3. 在仪表板中,我们使用与您设置的相同的列表生成逻辑来显示项目。
  4. 当您单击图像并重定向到Lease组件时,我们会触发该changeSelected功能。这发生在useEffect(),我们props.match.params.id用来获取我们导航到的租约的 id(也在 URL 中)Link
  5. 将该值传递给 changeSelected() ,它将selected使用列表中指定的租约对象更新 App 状态中的值。
  6. App.js重新渲染(由于状态更改)并将selected项目状态值传递给Lease,我们将使用它来显示有关该租约对象的信息。

总的来说,在集成 redux 之前,这是一种干净的方式。


推荐阅读