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

后端无唯一ID时如何创建React动态路由?

解决无唯一ID API的动态路由问题

针对API返回数据没有唯一ID的情况,你可以试试下面几种方案:

1. 使用数组索引作为临时ID

如果你的书籍列表不会频繁增删或排序,数组索引是最简单的临时方案:

路由配置(保持不变)

<Routes>
    <Route path="/book" element={<BooksView />} />
    <Route path="/book/:bookId" element={<BookDetailsView />} />
</Routes>

列表渲染时用索引

return(
  {books && (
    <ul>
      {books.map((book, index) => (
        <li key={index}>
          <Link to={`/book/${index}`}>{book.title}</Link>
        </li>
      ))}
    </ul>
  )}
)

详情页获取数据

在BookDetailsView里,把路由参数转成数字后匹配对应数据:

import { useParams } from 'react-router-dom';

function BookDetailsView() {
  const { bookId } = useParams();
  // 直接通过索引取对应书籍
  const book = books[Number(bookId)];
  // 后续渲染逻辑...
}

⚠️ 注意:如果列表有排序、新增或删除操作,索引会变化,导致路由指向错误,这种场景别用这个方案。

2. 生成数字类型的唯一ID

你之前用uuid没生效,大概率是没把生成的ID绑定到book对象上,或者路由参数处理时没对应上。如果需求必须是数字ID,可以用以下方式生成:

方式一:自增数字ID

获取到书籍列表后,给每个book添加一个自增的数字ID:

const booksWithNumIds = books.map((book, index) => ({
  ...book,
  numId: index + 1 // 从1开始,避免0可能带来的匹配问题
}));

然后渲染和路由就和原来带ID的逻辑一致:

{booksWithNumIds.map((book) => (
  <li key={book.numId}>
    <Link to={`/book/${book.numId}`}>{book.title}</Link>
  </li>
))}

方式二:从UUID提取数字部分

如果需要更唯一的数字ID,可以从UUID里提取数字并转成数字类型:

import { v4 as uuidv4 } from 'uuid';

const booksWithNumIds = books.map(book => ({
  ...book,
  numId: parseInt(uuidv4().replace(/[^0-9]/g, ''), 10) % 1000000 // 取部分数字避免数值过大
}));

3. 使用唯一字段组合生成路由参数

如果书籍有唯一的字段组合(比如标题+作者),可以把这些字段转成url友好的slug作为路由参数,比索引更稳定:

列表渲染

const generateBookSlug = (book) => {
  // 将标题和作者转成url友好的字符串
  return `${book.title.toLowerCase().replace(/\s+/g, '-')}-${book.author.toLowerCase().replace(/\s+/g, '-')}`;
};

return(
  {books && (
    <ul>
      {books.map((book) => (
        <li key={`${book.title}-${book.author}`}>
          <Link to={`/book/${generateBookSlug(book)}`}>{book.title}</Link>
        </li>
      ))}
    </ul>
  )}
)

路由配置(修改参数名更清晰)

<Routes>
    <Route path="/book" element={<BooksView />} />
    <Route path="/book/:bookSlug" element={<BookDetailsView />} />
</Routes>

详情页匹配数据

import { useParams } from 'react-router-dom';

function BookDetailsView() {
  const { bookSlug } = useParams();
  const book = books.find(item => {
    const itemSlug = `${item.title.toLowerCase().replace(/\s+/g, '-')}-${item.author.toLowerCase().replace(/\s+/g, '-')}`;
    return itemSlug === bookSlug;
  });
  // 后续渲染逻辑...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:20:47