You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Bootstrap下拉菜单触发VesselDetails组件并传参的实现问询

解决React Bootstrap下拉菜单点击展示VesselDetails的问题

看起来你已经顺利迈出了第一步,成功渲染出下拉菜单啦!接下来咱们一步步搞定交互逻辑和参数传递的问题,分两种常见场景来给你说明:


场景1:无需路由,同一页面内切换展示详情

这种方式适合不需要URL跳转的简单交互,直接通过组件状态控制展示:

1. 修改VesselDropdown组件

我们要去掉Dropdown.Item的href,换成点击事件来记录选中的船舶IMO,然后按需渲染VesselDetails并传递参数:

import React, { Component } from 'react';
import Dropdown from 'react-bootstrap/Dropdown';
import VesselDetails from './VesselDetails'; // 记得引入详情组件

class VesselDropdown extends Component {
  constructor(props) {
    super(props)
    this.state = { 
      vessels:[],
      selectedVesselimo: null // 新增状态,存储选中的船舶IMO
    }
  }

  componentDidMount() {
    fetch('http://localhost:3001/get/vessels')
      .then(res => res.json())
      .then((data) => { this.setState({ vessels: data }) })
      .catch(console.log)
  }

  // 新增下拉项点击处理函数
  handleVesselSelect = (vesselimo) => {
    this.setState({ selectedVesselimo: vesselimo });
  }

  render() {
    return (
      <div>
        <Dropdown>
          <Dropdown.Toggle variant="success" id="dropdown-basic">
            Select a Vessel
          </Dropdown.Toggle>
          <Dropdown.Menu>
            {/* 替换href为点击事件,添加唯一key */}
            { this.state.vessels.map(d => (
              <Dropdown.Item 
                key={d.vesselimo}
                onClick={() => this.handleVesselSelect(d.vesselimo)}
              >
                {d.vesselname}
              </Dropdown.Item>
            )) }
          </Dropdown.Menu>
        </Dropdown>

        {/* 选中船舶后才渲染详情组件,并传递IMO参数 */}
        {this.state.selectedVesselimo && (
          <VesselDetails vesselimo={this.state.selectedVesselimo} />
        )}
      </div>
    );
  }
}
export default VesselDropdown;

2. 修改VesselDetails组件接收参数并请求数据

现在组件可以通过props拿到vesselimo,还要注意当用户切换船舶时(参数变化),重新请求对应的数据:

import React, { Component } from 'react';
import Table from 'react-bootstrap/Table';

class VesselDetails extends Component {
  constructor(props) {
    super(props)
    this.state = { latestcalls: [] }
  }

  // 封装请求函数,方便复用
  fetchVesselData = (imo) => {
    fetch(`http://localhost:3001/get/latestcalls/${imo}`) // 用模板字符串替换参数
      .then(res => res.json())
      .then((data) => { this.setState({ latestcalls : data }) })
      .catch(err => console.error('请求详情失败:', err))
  }

  componentDidMount() {
    // 组件挂载时如果有参数就请求数据
    if (this.props.vesselimo) {
      this.fetchVesselData(this.props.vesselimo);
    }
  }

  // 当传入的IMO参数变化时,重新请求数据
  componentDidUpdate(prevProps) {
    if (this.props.vesselimo !== prevProps.vesselimo) {
      this.fetchVesselData(this.props.vesselimo);
    }
  }

  render() {
    return (
      <div>
        <h3>Port Calls for IMO {this.props.vesselimo}</h3>
        <Table striped bordered hover>
          <thead>
            <tr>
              <th>#</th>
              <th>Detail1</th>
            </tr>
          </thead>
          <tbody>
            {/* 遍历接口返回的港口数据 */}
            {this.state.latestcalls.map((call, index) => (
              <tr key={index}>
                <td>{index + 1}</td>
                <td>{call.detail1}</td> {/* 替换成你实际的字段名 */}
              </tr>
            ))}
          </tbody>
        </Table>
      </div>
    );
  }
}
export default VesselDetails;

场景2:使用React Router实现URL跳转(支持分享链接)

如果希望点击下拉项后URL同步更新(比如/vessels/1234567),适合需要分享页面链接的场景,需要用到react-router-dom:

1. 安装路由依赖

npm install react-router-dom

2. 在根组件配置路由(比如App.js)

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import VesselDropdown from './VesselDropdown';
import VesselDetails from './VesselDetails';

function App() {
  return (
    <Router>
      <div>
        {/* 下拉菜单放在路由外层,始终显示 */}
        <VesselDropdown />
        <Routes>
          {/* 配置详情页路由,接收imo参数 */}
          <Route path="/vessels/:imo" element={<VesselDetails />} />
        </Routes>
      </div>
    </Router>
  );
}

3. 修改VesselDropdown的下拉项为路由链接

用react-router-dom的Link组件替换原生的href,同时保留Bootstrap的样式:

import React, { Component } from 'react';
import Dropdown from 'react-bootstrap/Dropdown';
import { Link } from 'react-router-dom'; // 引入路由链接组件

class VesselDropdown extends Component {
  // ... 其他代码保持不变

  render() {
    return (
      <Dropdown>
        <Dropdown.Toggle variant="success" id="dropdown-basic">
          Select a Vessel
        </Dropdown.Toggle>
        <Dropdown.Menu>
          { this.state.vessels.map(d => (
            <Link 
              key={d.vesselimo}
              to={`/vessels/${d.vesselimo}`} // 跳转的路由路径
              className="dropdown-item" // 应用Bootstrap下拉项样式
            >
              {d.vesselname}
            </Link>
          )) }
        </Dropdown.Menu>
      </Dropdown>
    );
  }
}
export default VesselDropdown;

4. 修改VesselDetails从路由获取参数

用路由钩子useParams拿到URL中的imo参数,这里改成函数式组件更方便使用钩子:

import React from 'react';
import Table from 'react-bootstrap/Table';
import { useParams } from 'react-router-dom'; // 引入路由参数钩子

function VesselDetails() {
  const { imo } = useParams(); // 从URL中获取imo参数
  const [latestcalls, setLatestcalls] = React.useState([]);

  // 当imo变化时请求对应数据
  React.useEffect(() => {
    if (imo) {
      fetch(`http://localhost:3001/get/latestcalls/${imo}`)
        .then(res => res.json())
        .then(data => setLatestcalls(data))
        .catch(err => console.error('请求详情失败:', err))
    }
  }, [imo]);

  return (
    <div>
      <h3>Port Calls for IMO {imo}</h3>
      <Table striped bordered hover>
        <thead>
          <tr>
            <th>#</th>
            <th>Detail1</th>
          </tr>
        </thead>
        <tbody>
          {latestcalls.map((call, index) => (
            <tr key={index}>
              <td>{index + 1}</td>
              <td>{call.detail1}</td>
            </tr>
          ))}
        </tbody>
      </Table>
    </div>
  );
}

export default VesselDetails;

关键注意点:

  • 两种场景按需选择:第一种适合简单单页交互,第二种适合需要URL导航的场景。
  • 接口请求的URL要使用模板字符串(`...${imo}`),不然参数不会被正确替换。
  • 列表渲染一定要加key属性,避免React控制台警告。

内容的提问来源于stack exchange,提问作者Richard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:59:10