如何用数组索引而非对象编号路由至个人页面并实现搜索功能?
问题描述
我是useParams和ExpressJS的新手,目前正在尝试实现点击用户列表项后展示对应个人详情页的功能。用户资料以对象形式存储在数组中,当前浏览器链接使用的是用户的PROFILE_NUMBER(如https://localhost/3000/profile/A123),我希望改为使用数组索引(如https://localhost/3000/profile/1),同时需要实现搜索功能。
一、修改为数组索引路由
从前端路由跳转、后端接口逻辑、详情页数据匹配三个部分调整代码:
1. 前端Card组件:生成索引链接
修改map方法带上数组索引,将跳转链接指向索引而非PROFILE_NUMBER:
import React from "react"; import "./App.css"; import { Link } from "react-router-dom"; const Card = ({ profiles }) => { return ( <div className="App"> {profiles.map((profile, index) => ( <div className="container" key={profile.PROFILE_NUMBER}> <Link style={{ display: "block", margin: "1rem 0" }} to={`/profiles/${index}`} > <div> {profile.PROFILE_NUMBER} <br /> {profile.NAME} <br /> </div> </Link> </div> ))} </div> ); }; export default Card;
2. 前端Single组件:通过索引获取数据
直接用路由参数的索引从数组中取值,同时增加异常处理:
import React from "react"; import { useParams } from "react-router-dom"; import "./App.css"; const Single = ({ profiles }) => { const { profileIndex } = useParams(); const profile = profiles[Number(profileIndex)]; if (!profile) { return <div className="App">用户不存在</div>; } return ( <div className="App"> {`Report Number: ${profile.PROFILE_NUMBER}`} <br /> {`County: ${profile.NAME}`} <br /> {`Year: ${profile.AGE}`} <br /> {`Description: ${profile.HOBBY}`} </div> ); }; export default Single;
3. 修正后端函数引用与接口逻辑
先修正index.js中函数引用的错误,再增加索引有效性校验:
const express = require("express"); const { getProfiles } = require("./utils.js"); var cors = require("cors"); require("dotenv").config(); const PORT = process.env.PORT; const app = express(); app.use(cors()); app.get("/profiles", async (req, res) => { const profiles = await getProfiles(); res.json(profiles); }); app.get("/profiles/:profileIndex", async (req, res) => { const profiles = await getProfiles(); const index = Number(req.params.profileIndex); if (index >= 0 && index < profiles.length) { res.json(profiles[index]); } else { res.status(404).json({ message: "用户不存在" }); } }); app.listen(PORT, () => { console.log(`Express app listening on port ${PORT}!`); });
二、实现搜索功能
提供前端过滤和后端过滤两种方案,按需选择:
方案1:前端本地过滤(适合小数据量)
修改Card组件,添加搜索框和过滤逻辑:
import React, { useState } from "react"; import "./App.css"; import { Link } from "react-router-dom"; const Card = ({ profiles }) => { const [searchTerm, setSearchTerm] = useState(""); const filteredProfiles = profiles.filter(profile => { const lowerTerm = searchTerm.toLowerCase(); return profile.PROFILE_NUMBER.toLowerCase().includes(lowerTerm) || profile.NAME.toLowerCase().includes(lowerTerm); }); return ( <div className="App"> <input type="text" placeholder="搜索编号或姓名..." value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} style={{ margin: "1rem 0", padding: "0.5rem", width: "300px" }} /> {filteredProfiles.map((profile, index) => ( <div className="container" key={profile.PROFILE_NUMBER}> <Link style={{ display: "block", margin: "1rem 0" }} to={`/profiles/${index}`} > <div> {profile.PROFILE_NUMBER} <br /> {profile.NAME} <br /> </div> </Link> </div> ))} </div> ); }; export default Card;
方案2:后端接口过滤(适合大数据量)
1. 后端新增搜索接口
// 后端index.js新增接口 app.get("/profiles/search", async (req, res) => { const { q } = req.query; const profiles = await getProfiles(); if (!q) { return res.json(profiles); } const lowerQ = q.toLowerCase(); const filtered = profiles.filter(profile => profile.PROFILE_NUMBER.toLowerCase().includes(lowerQ) || profile.NAME.toLowerCase().includes(lowerQ) ); res.json(filtered); });
2. 前端Card组件调用后端接口
import React, { useState, useEffect } from "react"; import "./App.css"; import { Link } from "react-router-dom"; const Card = () => { const [searchTerm, setSearchTerm] = useState(""); const [profiles, setProfiles] = useState([]); useEffect(() => { fetch(`http://localhost:3000/profiles/search?q=${encodeURIComponent(searchTerm)}`) .then(res => res.json()) .then(data => setProfiles(data)); }, [searchTerm]); return ( <div className="App"> <input type="text" placeholder="搜索编号或姓名..." value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} style={{ margin: "1rem 0", padding: "0.5rem", width: "300px" }} /> {profiles.map((profile, index) => ( <div className="container" key={profile.PROFILE_NUMBER}> <Link style={{ display: "block", margin: "1rem 0" }} to={`/profiles/${index}`} > <div> {profile.PROFILE_NUMBER} <br /> {profile.NAME} <br /> </div> </Link> </div> ))} </div> ); }; export default Card;
3. 调整App.js的Card组件传参
// App.js中的Route部分 <Route exact path="/profile" element={<Card />} ></Route>
内容的提问来源于stack exchange,提问作者Elphinstone
相关产品推荐
相关产品推荐

