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

React Router v6:如何在新路由中管理点击项的Props

问题解答

你的当前方案是否可行?

你的方案可行,但存在几个明显缺陷:

  • 刷新详情页时,itemDetails 状态会丢失,导致详情组件无法渲染数据
  • 如果用户直接通过URL访问 /item/:itemId(比如书签、手动输入),状态是空的,组件无法正常工作
  • 状态耦合在路由组件中,不利于后续维护和扩展

更优的实现方案

推荐两种更可靠的方案:

方案一:通过URL参数重新获取数据

在详情组件中,利用useParams获取itemId,再从数据源(API、全局状态、本地存储等)重新获取对应项的完整数据:

// ItemDetails.tsx
import { useParams } from 'react-router-dom';
import { useEffect, useState } from 'react';

interface Item {
  id: string;
  // 其他属性
}

// 模拟数据源,实际可替换为API请求
const fetchItemById = async (id: string): Promise<Item> => {
  const items = [/* 你的对象数组 */];
  return items.find(item => item.id === id) as Item;
};

export const ItemDetails = () => {
  const { itemId } = useParams<{ itemId: string }>();
  const [item, setItem] = useState<Item | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!itemId) return;
    const getDetails = async () => {
      const data = await fetchItemById(itemId);
      setItem(data);
      setLoading(false);
    };
    getDetails();
  }, [itemId]);

  if (loading) return <div>加载中...</div>;
  if (!item) return <div>未找到该项目</div>;

  return (
    <div>
      <h1>{item.title}</h1>
      {/* 渲染其他详情内容 */}
    </div>
  );
};

这种方案的优势:

  • 支持刷新页面和直接访问URL
  • 组件解耦,详情组件不依赖父组件的状态传递
  • 符合路由设计的单一职责原则

方案二:使用React Router的state传递数据

跳转时通过navigate函数的第二个参数传递完整item数据,详情组件通过useLocation获取:

// ItemList.tsx
import { useNavigate } from 'react-router-dom';

interface ItemListProps {
  items: Item[];
}

export const ItemList = ({ items }: ItemListProps) => {
  const navigate = useNavigate();

  const handleItemClick = (item: Item) => {
    navigate(`/item/${item.id}`, { state: { item } });
  };

  return (
    <div>
      {items.map(item => (
        <div key={item.id} onClick={() => handleItemClick(item)}>
          {/* 渲染列表项 */}
        </div>
      ))}
    </div>
  );
};

// ItemDetails.tsx
import { useLocation } from 'react-router-dom';

export const ItemDetails = () => {
  const location = useLocation();
  const item = location.state?.item as Item;

  if (!item) {
    // 可选择跳回列表或重新获取数据
    return <div>数据加载失败</div>;
  }

  return (
    <div>
      <h1>{item.title}</h1>
      {/* 渲染详情 */}
    </div>
  );
};

注意事项:

  • 这种方式会在刷新页面时丢失数据,因为state存储在内存中
  • 适合临时数据传递,或作为重新获取数据的补充(比如先使用state中的数据,刷新时再重新请求)

总结

如果数据来自持久化数据源(API、数据库),优先选方案一;如果只是临时传递数据且不介意刷新丢失,可使用方案二。你的原始方案虽能工作,但在页面刷新和直接访问URL的场景下会失效,不推荐用于生产环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:30:41