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

如何用数组索引而非对象编号路由至个人页面并实现搜索功能?

问题描述

我是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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:58:03