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

React Router中Route的component属性与children写法有什么差异?

React Router 两种Route写法的差异解答

核心差异触发前提

你没有观察到差异,是因为你的示例中App组件没有状态更新逻辑,不会触发重渲染,两种写法的差异只有在父组件(App)发生重渲染、且当前路由未切换时才会显现。

两种写法的底层逻辑区别

1. path='/uno'的component传内联函数写法

你写的<Route path='/uno' component={(props) => <PropComp {...props}/>}/>存在一个问题:component属性接收的是每次App渲染都会重新生成的匿名函数,React Router v5的component属性逻辑是:

  • 只要传入的组件引用发生变化,就会直接卸载旧的组件实例,创建并挂载新的实例
  • 这会直接导致PropComp的空依赖useEffect每次App重渲染都触发,同时组件内的counter状态会被清空重置

如果你改成component={PropComp}直接传组件引用,就不会有这个问题,和children写法的挂载表现一致。

2. path='/dos'的children写法

直接把<PropComp/>写在Route标签内部的写法,组件的实例引用是稳定的,即使App重渲染,只要路由没有切换,PropComp就不会被卸载重挂载,状态会保留,空依赖的useEffect也只会在第一次路由匹配时触发一次。

验证测试方法

你可以给App组件添加状态更新逻辑,就能直观看到差异:

// 修改后的App.js
import { BrowserRouter as Router, Link, Route } from 'react-router-dom';
import { PropComp } from './PropComp';
import { useState } from 'react';

function App() {
  // 新增App自身的状态
  const [appCount, setAppCount] = useState(0)
  return (
    <div className="App">
      {/* 新增触发App重渲染的按钮 */}
      <button onClick={() => setAppCount(prev => prev + 1)}>触发App更新  当前计数:{appCount}</button>
      <Router>
        <Link to='/uno'>uno</Link>
        <p>...</p>
        <Link to='/dos'>dos</Link>
        <Route path='/uno' component={(props) => <PropComp {...props}/>}/>
        <Route path='/dos'>
          <PropComp/>
        </Route>
      </Router>
    </div>
  );
}

export default App;

测试步骤:

  • 切换到/uno路由,点击Sum按钮把counter调到5,点击上方的触发App更新按钮,会看到counter清零,控制台多打印一次PropComp mounted
  • 切换到/dos路由,同样把counter调到5,点击触发App更新按钮,counter不会变化,控制台也不会新增挂载日志

为什么修改动画示例没有看到变化?

动画过渡示例的场景是路由切换时的动画,路由切换本身就会触发组件的卸载和挂载,两种写法在路由切换时的表现一致,所以你看不到差异。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:45:03