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
相关产品推荐
相关产品推荐

