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

非路由场景下如何为React组件传递React Router Loader数据?

React Router嵌套子组件获取Loader数据的解决方案

问题核心

React Router的loader机制仅作用于路由直接渲染的组件,通过useLoaderData()接收预加载数据。但当将依赖loader数据的组件(如HostVans)作为子组件嵌套在其他组件(如Dashboard)中时,useLoaderData()无法获取到数据,直接传递loader属性给子组件也不生效。

可行解决方案

方案1:给父组件路由添加Loader,通过Props传递数据

给Dashboard对应的路由添加hostVansLoader,在Dashboard中获取数据后通过props传递给HostVans,同时修改HostVans兼容两种数据来源。

步骤1:修改路由配置(App.jsx)

给Dashboard路由添加loader:

<Route path="host" element={<HostLayout />} >
  <Route index element={<Dashboard />} loader={hostVansLoader} /> {/* 添加loader */}
  {/* 其他路由保持不变 */}
</Route>

步骤2:在Dashboard中传递数据(Dashboard.jsx)

使用useLoaderData()获取数据,再通过props传给HostVans:

import { Link, useLoaderData } from "react-router-dom";
import { FaStar } from "react-icons/fa6";
import HostVans from "./HostVans";

const Dashboard = () => {
  const vans = useLoaderData();
  
  return (
    <>
      {/* 原有Dashboard内容 */}
      <div className="container dashboard-container">
        <section className="row income-section">
          <div className="col-10">
            <h1 className="income-heading">Welcome!</h1>
            <p>Income last <span>30 days</span></p>
            <p className="income-figure">$2,260</p>
          </div>
          <div className="col-2">
            <Link to="#">Details</Link>
          </div>
        </section>
        <section className="row reviews-section">
          <div className="col-10">
            <h2 className="reviews-heading">Review score</h2>
            <FaStar className="reviews-icon"/>
            <p className="review-score">5.0<span>/5</span></p>
          </div>
          <div className="col-2">
            <Link to="#">Details</Link>
          </div>
        </section>
      </div>
      {/* 通过props传递vans数据 */}
      <HostVans vans={vans} />
    </>
  )
}

export default Dashboard

步骤3:修改HostVans兼容两种数据来源(HostVans.jsx)

优先使用props传入的数据,没有则使用useLoaderData():

import { useSearchParams, useLoaderData } from "react-router-dom";

const HostVans = ({ vans: propsVans }) => {
  const loaderVans = useLoaderData();
  const vans = propsVans || loaderVans;

  if (!vans) {
    return <div>Loading...</div>; // 处理加载状态
  }

  // 原有组件逻辑,使用vans数据
  return (
    {/* 组件内容 */}
  )
}

export default HostVans

方案2:在HostVans内部兜底请求数据

如果不想修改路由配置,可以在HostVans中判断,当没有loader数据时,通过useEffect主动请求数据,兼容两种使用场景。

修改HostVans.jsx:

import { useSearchParams, useLoaderData } from "react-router-dom";
import { useState, useEffect } from "react";
import { getHostVans } from "./path-to-your-api"; // 导入数据请求函数

const HostVans = () => {
  const loaderVans = useLoaderData();
  const [vans, setVans] = useState(loaderVans);

  useEffect(() => {
    // 仅当没有loader数据时发起请求
    if (!loaderVans) {
      const fetchVans = async () => {
        const data = await getHostVans();
        setVans(data);
      };
      fetchVans();
    }
  }, [loaderVans]);

  if (!vans) {
    return <div>Loading...</div>;
  }

  // 原有组件逻辑
  return (
    {/* 组件内容 */}
  )
}

export default HostVans

方案3:使用useRouteLoaderData复用已加载的Loader数据(React Router v6.4+)

给host/vans路由的loader添加唯一ID,在HostVans中通过useRouteLoaderData获取该loader的数据,前提是用户已访问过host/vans路由(数据已被缓存)。

步骤1:给路由添加loader ID(App.jsx)

<Route 
  path="vans" 
  element={<HostVans />}
  errorElement={<Error />}
  loader={hostVansLoader}
  id="host-vans-loader" {/* 添加唯一ID */}
/>

步骤2:在HostVans中获取数据(HostVans.jsx)

import { useSearchParams, useLoaderData, useRouteLoaderData } from "react-router-dom";

const HostVans = () => {
  // 优先复用已加载的路由loader数据,没有则使用当前组件的loader数据
  const vans = useRouteLoaderData("host-vans-loader") || useLoaderData();

  if (!vans) {
    return <div>Loading...</div>;
  }

  // 原有组件逻辑
  return (
    {/* 组件内容 */}
  )
}

export default HostVans

推荐方案

优先选择方案1,它延续了React Router loader预加载数据的设计优势,避免了组件内部重复请求,同时完美兼容路由渲染和嵌套子组件两种场景。

内容的提问来源于stack exchange,提问作者Juan Manuel Linares

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 01:27:37