react-router使用总结,以及加载进度条的使用

安装

pnpm add react-router-dom@6

yarn add react-router-dom@6

引入

//index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {
    BrowserRouter as Router
} from 'react-router-dom'

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
      <Router>
          <App />
      </Router>
  </React.StrictMode>
);


reportWebVitals();
//App.tsx
import React, {Suspense, lazy, ComponentType} from 'react';
import {
    Routes,
    Route,
} from 'react-router-dom'


//着急加载的模块直接加载
import Header from "./components/Header";
import Footer from "./components/Footer";
import Loading from "./components/Loading";
//不着急加载的模块使用懒加载
const Home = lazy((): Promise<{ default: ComponentType<any> }> => {
    return import('./pages/Home')
})
const About = lazy((): Promise<{ default: ComponentType<any> }> => {
    return import('./pages/About')
})
const History = lazy((): Promise<{ default: ComponentType<any> }> => {
    return import('./pages/History')
})


const App: React.FC<{}> = () => {
    return (
        <React.Fragment>
            <Header/>
            <Suspense fallback={<Loading/>}>  //加载时会使用Loading组件加载后会被替换成真正的路由组件,用于做页面的loading状态
                <main id='main'>
                    <Routes>
                        <Route path="/" element={<Home/>}/>
                        <Route path="/history" element={<History/>}/>
                        <Route path="/about" element={<About/>}/>
                    </Routes>
                </main>
            </Suspense>
            <Footer/>
        </React.Fragment>
    );
}

export default App;

页面跳转

  • NavLink和Link的区别在于NavLink在当前路由时会加上一个active的类
  • NavLink组件的style或className可以接收一个函数,函数接收一个isActive参数,可根据该参数调整样式

1.标签模式的跳转(NavLink,Link)

//Header.tsx
import { NavLink } from 'react-router-dom';function Foo(){
    return (
        <NavLink
            style={ (isActive) => ({color: isActive ? 'red' : '#fff'}) }
        >Click here</NavLink>
    )
}

2.编程模式的跳转(useNavigate )

import React from "react";
import { useNavigate } from "react-router-dom";

interface Props {
}
const Home: React.FC<Props> = () => {
    const navigate = useNavigate();
    const redirect=()=>{
        navigate("/about")
    }
    return (
        <React.Fragment>
            <button onClick={redirect}>跳转</button>
        </React.Fragment>
    )
}

获取路由参数 (useParams)

<Routes>
    <Route path="/test/:id" element={<Test/>}/>
</Routes>
import React from "react";
import {useParams} from 'react-router-dom'

interface Props{

}

const Test:React.FC<Props> =()=>{
    const  params = useParams();
    return(
        <div>{params.id}</div>
    )
}

export default Test

获取查询参数

eg: /login?name=lgp

import React from "react";
import {useParams,NavLink, Outlet,useSearchParams,} from 'react-router-dom'

interface Props {

}

const Test: React.FC<Props> = () => {
    const params=useParams()
    const [searchParams, setSearchParams] = useSearchParams()
    if(searchParams.get("name")) console.log(searchParams.get("name"))   //获取查询参数
    return (
        <>
            <nav>
                <NavLink to="/test/login?name=lgp" style={{marginRight:'30px'}}>login</NavLink>
                <NavLink to="/test/register" style={{marginRight:'30px'}}>register</NavLink>
                <NavLink to="/test/xxx">params</NavLink>
            </nav>
            <div>
                <Outlet/>
            </div>
            <div>
                {params.id?params.id:"yyy"}
            </div>

        </>
    )
}

export default Test

嵌套路由

//App.tsx
 <Route path="/test" element={<Test/>}>
     <Route index element={<Register/>}/>     //索引路由 即在/test时,子路由将呈现Register组件
    <Route path="login" element={<Login/>}/>
    <Route path="register" element={<Register/>}/>              
    <Route path=":id" element={<Loading/>}/>
 </Route>

这将匹配下面三个路由

  • “/test/login”
  • “/test/register”
  • “/test/:id”

父组件需要用( <Outlet />)标签呈现子组件

import React from "react";
import {useParams,NavLink, Outlet} from 'react-router-dom'

interface Props {

}

const Test: React.FC<Props> = () => {
    const params=useParams()

    return (
        <>
            <nav>
                <NavLink to="/test/login" style={{marginRight:'30px'}}>login</NavLink>
                <NavLink to="/test/register" style={{marginRight:'30px'}}>register</NavLink>
                <NavLink to="/test/xxx">params</NavLink>
            </nav>
            <div>
                <Outlet/>     //将被子路由组件替换
            </div>
            <div>
                {params.id?params.id:"yyy"}   //获取路由路径参数
            </div>

        </>
    )
}

export default Test

索引路由

您可以在路由层次结构的任何级别拥有索引路由,该路由将在父级匹配时呈现,但其他子级都不匹配。

 <Route path="/test" element={<Test/>}>
    <Route index element={<Register/>}/>     //索引路由 即在/test时,子路由将呈现Register组件
    <Route path="login" element={<Login/>}/>
    <Route path="register" element={<Register/>}/>              
    <Route path=":id" element={<Loading/>}/>
 </Route>

404路由

当没有其他路由与 URL 匹配时,可以使用 呈现“未找到”路由。
<Route path="*" element={<NotFound />} />

 <Routes>
      <Route path="/" element={<Home />} />
      <Route path="dashboard" element={<Dashboard />} />
      <Route path="*" element={<NotFound />} />   //放在最后做兜底
    </Routes>

布局路由

<Routes>
  <Route path="/" element={<App />}>
    <Route index element={<Home />} />
    
    <Route element={<PageLayout />}>                           //布局路由不参与匹配
      <Route path="/privacy" element={<Privacy />} />
      <Route path="/tos" element={<Tos />} />
    </Route>
    
  <Route path="contact-us" element={<Contact />} />
</Routes>

渲染结果
/privacy

<App>
  <PageLayout>
    <Privacy />
  </PageLayout>
</App>

/tos

<App>
  <PageLayout>
    <Tos />
  </PageLayout>
</App>

也可以被其他方式代替(不建议)

<Route
    path="/privacy"
    element={
      <PageLayout>
        <Privacy />
      </PageLayout>
    }
  />
  <Route
    path="/tos"
    element={
      <PageLayout>
        <Tos />
      </PageLayout>
    }
  />

路由器模式

  • BrowserRouter 是在 Web 浏览器中运行 React Router 的推荐接口,使用干净的 URL 将当前位置存储在浏览器的地址栏中,并使用浏览器的内置历史记录堆栈进行导航。
import * as React from "react";
import * as ReactDOM from "react-dom";
import App from './App'
import { BrowserRouter } from "react-router-dom";

ReactDOM.render(
  <BrowserRouter>
    <App/>
  </BrowserRouter>,
  root
);
  • HashRouter用于 Web 浏览器,当 URL 由于某种原因不应(或不能)发送到服务器时。在某些共享宿主方案中,您可能会完全控制服务器,这可能会发生这种情况。在这些情况下,可以将当前位置存储在当前 URL 的部分,因此永远不会将其发送到服务器。
import { HashRouter } from "react-router-dom";

//同上
  • HistoryRouter 将历史库的实例作为 prop。这允许您在非 React 上下文中使用该实例或将其用作全局变量。
import * as React from "react";
import * as ReactDOM from "react-dom";
import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom";
import { createBrowserHistory } from "history";

const history = createBrowserHistory({ window });

ReactDOM.render(
  <HistoryRouter history={history}>
    {/* The rest of your app goes here */}
  </HistoryRouter>,
  root
);
  • MemoryRouter
不建议使用
  • NativeRouter是在 React Native 应用程序中运行 React Router 的推荐接口
import * as React from "react";
import { NativeRouter } from "react-router-native";

function App() {
  return (
    <NativeRouter>
      {/* The rest of your app goes here */}
    </NativeRouter>
  );
}

`编程式路由导航用useNavigate代替useHistory

go goBackgoForward`

import { useNavigate } from 'react-router-dom'
const app=()=>{

  const navigate = useNavigate()
  function handleClick() {
     history.push('/home');
     //navigate('/home', {replace: true});
   };
  return (
    <button onClick={handleClick}>Submit</button>
    <button onClick={() => navigate(-2)}>
      Go 2 pages back
    </button>
    <button onClick={() => navigate(-1)}>Go back</button>
    <button onClick={() => navigate(1)}>
      Go forward
    </button>
    <button onClick={() => navigate(2)}>
      Go 2 pages forward
    </button>
  )
}

重定向

    const location = useLocation();

    if (!isLogin) {
        return <Navigate to="/login" state={{from: location}} replace/>;
    }

给路由添加进度条

pnpm add nprogress
pnpm add @types/nprogress -D
路由我们使用懒加载的方式加载

//App.tsx
import React, {Suspense, lazy, ComponentType} from 'react';
import Loading from "./components/Loading";
import {
    Routes,
    Route,
} from 'react-router-dom'
const Home = lazy((): Promise<{ default: ComponentType<any> }> => {
    return import('./pages/Home')
})
const About = lazy((): Promise<{ default: ComponentType<any> }> => {
    return import('./pages/About')
})
const History = lazy((): Promise<{ default: ComponentType<any> }> => {
    return import('./pages/History')
})
const NotFound = lazy((): Promise<{ default: ComponentType<any> }> => {
    return import('./pages/NotFound')
})

const App: React.FC<{}> = () => {
    return (
        <React.Fragment>
            <Header/>
            <Suspense fallback={<Loading/>}>       //这里我们使用loading组件
                <main id='main'>
                    <Routes>
                        <Route path="/" element={<Home/>}/>
                        <Route path="/history" element={<History/>}/>
                        <Route path="/about" element={<About/>}/>
                        <Route path="*" element={<NotFound/>}/>
                    </Routes>
                </main>
            </Suspense>
            <Footer/>
        </React.Fragment>
    );
}

export default App;

loading组件

import React, {useEffect} from "react";
import nprogress from "nprogress";
import "nprogress/nprogress.css";

//配置
nprogress.configure({
    easing: 'ease', // 动画方式
    speed: 500, // 递增进度条的速度
    showSpinner: false, // 是否显示加载ico
    trickleSpeed: 200, // 自动递增间隔
    minimum: 0.3, // 初始化时的最小百分比
});

const Loading:React.FC<{}>=()=>{
    //组件挂在时执行nprogress.start()
    useEffect(() => {
        nprogress.start()
    }, [])
    //组件消亡时执行 nprogress.done()
    useEffect(() => {
        return () => {
            nprogress.done()
        }
    })
  return (
      <React.Fragment />
  )
}

export default Loading

自定义导航条的背景颜色,只需要修改下面的元素的背景颜色就行
注意修改的css文件引入要在nprogress.css文件后面否则不能覆盖样式失效

#nprogress .bar{
  background-color: #df4402;
}

useSubmit

如果您希望某人在一段时间不活动后自动从您的网站注销,这也很有用。在本例中,我们将不活动定义为用户在 5 分钟后没有导航到任何其他页面。

import { useSubmit, useLocation } from "react-router-dom";
import { useEffect } from "react";

function AdminPage() {
  useSessionTimeout();
  return <div>{/* ... */}</div>;
}

function useSessionTimeout() {
  const submit = useSubmit();
  const location = useLocation();

  useEffect(() => {
    const timer = setTimeout(() => {
      submit(null, { method: "post", action: "/logout" });
    }, 5 * 60_000);

    return () => clearTimeout(timer);
  }, [submit, location]);
}
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值