React-Router6版本的更新引起的路由用法變化

React Router應該是React生態系統中最受歡迎的庫瞭,npm周下載量達600w+,github也有45.2k的加星,足以說明它是一款非常優秀的庫,作為React社區重要的庫,它經歷瞭多次迭代和重大更改,就在上個月,更是迎來瞭一個大的正式版更新6.x,當前最新為6.0.2,相對比於之前的5.x版本做出瞭較大改變,不管從用法還是從性能上都有瞭明顯的提升,本文也將用新老版本對比的方式讓你能以最快的速度上手新用法

話不多說,先列出6.0做出的改變之處:

  1. 用法變化
  2. 替換為
  3. 嵌套路由新寫法
  4. 推出全新hook,全面擁抱函數組件
  5. 基於對象的路由,實現js配置所有路由
  6. 整體代碼比上個版本減小大約70%

用法變化

組件變化較大,移除瞭component與render屬性,使用element屬性替代,因為與之前的版本代碼寫法不能兼容,寫法區別如下 

  // 5.x用法
   <Route path="/home" component={Home} />
   <Route path="/login" render={()=><Login/>}/>

   // 6.x用法
   <Route path="/home" element={<Home/>} />
   <Route path="/login" component={<Login/>} />

替換為

v6版本移除瞭 組件,並使用替換,除瞭能替代 組件的功能外,也做瞭一些改變,比如所有的都必須包裹在中,否則拋出錯誤

 // 5.x用法
   <Switch>
       <Route path="/home" component={Home} />
       <Route path="/login" component={Login} />
   </Switch>

   // 6.x用法
    <Routes>
       <Route path="/home" element={<Home/>} />
       <Route path="/login" component={<Login/>} />
   </Routes>

嵌套路由

v6版本的react-router支持多種嵌套路由寫法,寫法分別如下:

第一種寫法:延續v5版本寫法,保持原有組件結構 這種寫法比較適合重構的項目,不需要改變太多的代碼便能過渡到v6版本

  // App.jsx
   <Routes>
       <Route path="/home" element={<Home/>} />
       <Route path="/user/*" element={<User/>} />
   </Routes>

   // User.jsx
   <Routes>
       <Route path="profile" element={<UserProfile/>} />
       <Route path=":/id" element={<UserDetail/>} />
   </Routes>

雖然組件結構與v5版本一至,但寫法上有一定的差異,父組件App.jsx中的path屬性最後必須使用星號(path="/user/*"),子組件User.jsx中的路徑都是相對於其父級路徑,所以不需要像v5版本那樣寫全整個路徑,媽媽再也不用擔心我會寫錯地址。

另外,如果中的path屬性不以/開頭,則是相對於其父級路徑,這樣的好處是使嵌套路由實現變得更加簡單,並易於組合復雜的路由和佈局

第二種寫法:把所有的寫在一起,配合實現路由組件的顯示

 // App.jsx
   <Routes>
       <Route path="/home" element={<Home/>} />
       <Route path="/user" element={<User/>}>
           <Route path="profile" element={<UserProfile/>} />
           <Route path=":/id" element={<UserDetail/>} />
       </Route>
   </Routes>

   // User.jsx
   <Outlet/>

這樣寫法讓我們能更清晰地去瞭解路由結構,能更好地管理我們的路由,而能讓我們能更精確地把嵌套的路由組件佈局到需要位置顯示

第三種寫法:使用useRoutes()實現路由配置

使用useRoutes配置路由與配置路由效果一致,隻是這種寫法使用javascript生成路由,不依賴JSX,返回相應結構的路由組件樹,有木有感覺回到瞭VueRouter?有木有?

 function App(){
       // 以下寫法與第二種寫法效果一至
       const element = useRoutes([
          {path:'/home',element:<Home/>},
          {
               path:'/user',
               element:<User/>,
               children:[
                  {path:'profile',element:<UserProfile/>},
                  {path:':/id',element:<UserDetail/>},
              ]
          }
      ])
       return element
  }

以上三種寫法各有各的優點,開發者可以根據自身的需求選擇一種來實現你的嵌套路由

重定向

新版本的react-router移除瞭組件,但可以使用新增的組件配合組件實現重定向效果

<Routes>
       <Route path="/home" element={<Home/>} />
       <Route path="/" element={<Navigate to="/home"/>}>
   </Routes>

路由跳轉

路由配置好後免不瞭要進行頁面跳轉,但新版的react-router移除瞭history對象,故不能使用v5版本的history(包括useHistory hook)已不能使用,我們可以使用以下兩中方式進行跳轉

使用或進行跳轉這種方式與上一個版本幾乎沒有太大的區別,唯一的區別是組件的高亮寫法發生瞭變化

   // v5版本
   <NavLink to="/home" activeStyle={{color:'#f00'}}>首頁</NavLink>
   <NavLink to="/home" activeClassName="active">首頁</NavLink>

   // v6版本
   <NavLink to="/home" style={({isActive})=>(isActive?{color:'#f00'}:{})}>首頁</NavLink>
   <NavLink to="/home" className={({isActive})=>isActive?'current':''}>首頁</NavLink>

PS: 默認已經有一個高亮的active類,可以直接使用,不需要額外設置
使用useNavigate()進行跳轉有時候我們並不能使用以上兩個組件進行跳轉,如根據ajax請求返回值跳轉不同的頁面,這時我們就得使用js的方式時行跳轉瞭,雖然新版的react-router已經移除掉history對象,但給我們提供瞭 useNavigate hook實現路由跳轉,使用方法如下

 import { useNavigate } from "react-router-dom";
   let navigate = useNavigate();
   navigate(`/home`);

   // 跳轉且不保留瀏覽記錄
   navigate(`/home`,{replace:true});

   // 返回上一頁
   navigate(-1)

   // 對象方式跳轉
   navigate({
       pathname:'/home'
  })

需要註意一點就是,在v6版本的react-router中,如果跳轉的路徑如果不是以/開頭,則為相對路徑,相對於其父級路由路徑,這樣的設置能讓我們更好的控制跳轉

路由傳參

我們都知道,在進行路由跳轉時,可以附帶一些參數一起傳遞到跳轉頁面,新版的react-router已經從props中移除瞭history、location、match,也移除掉瞭withRouter高階組件,所以無法使用老版本的方式傳參與接收,新版用法如下

search傳參

 let navigate = useNavigate();
   navigate(`/home?page=1&size=10`);
   navigate({
       pathname:'/home',
       search:'page=1&size=10'
  });

在對應組件接收參數也很簡單,使用useSearchParams hook進行接收,得到URLSearchParams對象以及設置search參數函數組成的數據

   function Home(){
       const [searchParams,setSearchParams] = useSearchParams()
       searchParams.get('page');//1
       searchParams.get('size');//10
       return (
           <div>首頁</div>
      )
  }

動態路由傳參

   <Route path="/user" element={<User/>}>
       <Route path=":/id" element={<UserDetail/>} />
   </Route>

配置完以上路由後,當頁面跳轉到/user/123這個路徑時,可以在組件中使用useParams hook獲取123這個id

function UserDetail(){
       const {id} = useParams()
       return (
           <div>id:{id}</div>
      )
  }

state傳參通過、或 useNavigate進行跳轉時,都可以傳遞state參數,用法如下:

 <Link to="/home" state={{idx:1,key:'qf'}}>首頁</Link>
   navigate('/home',{state:{idx:1,key:'qf'}})

在首頁組件中通過useLocation hook獲取state值

 function Home(){
       const {state} = useLocation();
       state.idx; // 1
       state.key; // qf
       return (
           <div>首頁</div>
      )
  }

其他

另外,React路由同樣支持SSR服務端渲染等其它功能,由於篇幅在限,在此不做過多說明,感興趣的小夥伴請繼續關註我,後續的寫文章專門介紹react-router在在服務端的用法。

總結

以上就是本文的所有內容,希望通過該文章能讓大傢對新版本react-router有個全面的認識,以便在項目中應用新版路由。更多相關React-Router6路由內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: