升级!react-router V5到react-router V6----结合项目

千锋前端-React全家桶_React项目实战全球新闻发布管理系统_哔哩哔哩_bilibili

该项目的路由部分是用react-router V5写的,但是react的路由目前已经更新到V6版本,因此将项目中的路由部分更新了一下。主要包括如下几个方面:

一. 

1. v6 版本中移出了先前的 ,引入了新的替代者:
2. 要配合使用,且必须要用 包裹
3. 相当于一个 if 语句,如果其路径与当前 URL 匹配,则呈现其对应的组件。
4. 属性用于指定:匹配时是否区分大小写(默认为 false )。
5. URL 发生变化时, 都会查看其所有子 元素以找到最佳匹配并呈现组件 。
6. 也可以嵌套使用,且可配合 useRoutes() 配置 路由表 ,但需要通过 组件
来渲染其子路由。
结合项目:
V5版本:
export default function IndexRouter() {
    return (
        
            
                {/* login,news,detail,/这四个可以拿到路由组件提供的props,但是NewsSandBox拿不到 */}
                
                {/* 下面这两个是作为游客身份登陆时可以访问到的组件 */}
                
                
                {/*  */}
            
        
    )
}
V6版本:
export default function IndexRouter() {
    return (
        
            {/* react-route V6版本中HashRouter 里面包 Switch 会出错,改为包 Routes (Routes 和 Switch 的功用是一样的,都能做到精准匹配) */}
            
                {/* Route 的 component 属性改为 element,并且 element 中使用 <> 包裹组件名称 */}
                } />
                {/* 下面这两个是作为游客身份登陆时可以访问到的组件 */}
                } />
                } />
                {/*  */}
            
        
    )
}

二. 重定向Navigate

1. 作用:只要 组件被渲染,就会修改路径,切换视图。
2. replace 属性用于控制跳转模式( push replace ,默认是 push )。
结合项目:
V5版本:
                
                    localStorage.getItem("token") ?
                         :
                        
                } />
V6版本:
import { Navigate } from 'react-router-dom'
// ...
                 :
                        // 重定向时需要将 Redirect 改为 Navigate,并且一样使用的是 element 而不是 render
                        
                } />

三. 废除withrouter,使用Hooks

1. useNavigate()

作用:返回一个函数用来实现编程式导航。结合项目:

V5版本:

function SideMenu(props) {
  // 使用withroute高阶组件,使该组件可以接受到路由组件传来的props属性
  // 获取当前url中的key值,传入Menu中,作为选中/展开条件
  ....
  ....
  const renderMenu = (menuList) => {
    ....
      return checkPagePermission(item) &&  {
        props.history.push(item.key)
      }}>{item.title}
    })
  }
  const selectKeys = [props.location.pathname]
  const openKeys = ["/" + props.location.pathname.split("/")[1]]
  return (
   ....
}
export default connect(mapStateToProps)(withRouter(SideMenu))

V6版本:

import { useNavigate, useLocation } from "react-router";
function SideMenu(props) {
  let navigate = useNavigate();
  ......
  ......
  const renderMenu = (menuList) => {
    ......
      return checkPagePermission(item) &&  {
        navigate(item.key)
      }}>{item.title}
    })
  }
  // V6写法
  let location = useLocation();
  const selectKeys = [location.pathname];
  const openKeys = ["/" + location.pathname.split("/")[1]];
  return (
   .......
  )
}

2. useParams

1. 作用:回当前匹配路由的 params 参数,类似于 5.x 中的 match.params 。项目中对比:
V5版本:
 const [newsInfo, setnewsInfo] = useState(null)
    useEffect(() => {
        axios.get(`/news/${props.match.params.id}?_expand=category&_expand=role`).then(res => {
            setnewsInfo({
                ...res.data,
                // 每刷新一次就把view的值加一
                view: res.data.view + 1
            })
            //同步后端
            return res.data
        }).then(res => {
            axios.patch(`/news/${props.match.params.id}`, {
                view: res.view + 1
            })
        })
    }, [props.match.params.id])
    const handleStar = () => {
        // 本地和数据库都要更新数据
        setnewsInfo({
            ...newsInfo,
            star: newsInfo.star + 1
        })
        axios.patch(`/news/${props.match.params.id}`, {
            star: newsInfo.star + 1
        })
    }
V6版本:
import { useParams } from "react-router";
const params = useParams();
const [refresh, setRefresh] = useState(false);
export default function Detail(props) {
    const [newsInfo, setnewsInfo] = useState(null)
    let star = localStorage.getItem("star") || [];
    useEffect(() => {
        axios.get(`/news/${params.id}?_expand=category&_expand=role`).then(res => {
            setnewsInfo({
                ...res.data,
                // 每刷新一次就把view的值加一
                view: res.data.view + 1
            })
            //同步后端
            return res.data
        }).then(res => {
            axios.patch(`/news/${params.id}`, {
                view: res.view + 1
            })
        })
    }, [refresh])
    const handleStar = () => {
        if (!star.includes(params.id.toString())) {
            updateNews(params.id, {
                star: newsInfo.star + 1,
            })
                .then(() => {
                    setRefresh();
                    const arr = [...star];
                    localStorage.setItem("star", arr.concat(params.id));
                })
                .catch((e) => console.log(e));
        } else {
            notification.info({
                message: `error`,
                description: `starError`,
                placement: "bottomRight",
            });
        }
    };
    ......
}

四. 其它

1. useRoutes()

1. 作用:根据路由表,动态创建
2. 示例代码:
//路由表配置:src/routes/index.js 
import About from '../pages/About'
import Home from '../pages/Home' 
import {Navigate} from 'react-router-dom'
export default [ 
    { path:'/about', element: },
    { path:'/home', element: },
    { path:'/', element: } 
]
//App.jsx 
import React from 'react' 
import {NavLink,useRoutes} from 'react-router-dom' 
import routes from './routes' 
export default function App() { 
    //根据路由表生成对应的路由规则 
    const element = useRoutes(routes) 
    return (
         
...... {/* 注册路由 */} {element} ......
) }

2. useLocation()

1. 作用:获取当前 location 信息,对标 5.x 中的路由组件的 location 属性。
2. 示例代码:
import React from 'react' 
import {useLocation} from 'react-router-dom' 
export default function Detail() { 
    const x = useLocation() 
    console.log('@',x) // x就是location对象:
    /* { 
    hash: "", 
    key: "ah9nv6sz", 
    pathname: "/login", 
    search: "?name=zs&age=18", 
    state: {a: 1, b: 2} 
    }*/
    return ( 
        
  • 消息编号:{id}
  • 消息标题:{title}
  • 消息内容:{content}
) }

3. useMatch()

1. 作用:返回当前匹配信息,对标 5.x 中的路由组件的 match 属性。
2. 示例代码:
}/>
登录
export default function Login() { 
const match = useMatch('/login/:x/:y') 
console.log(match) //输出match对象 
//match对象内容如下: /*
{ 
    params: {x: '1', y: '10'} 
    pathname: "/LoGin/1/10" pathnameBase: "/LoGin/1/10" 
    pattern: { path: '/login/:x/:y',
    caseSensitive: false, 
    end: false } 
} */
    return ( 
    

Login

) }

4. useInRouterContext()

作用:如果组件在 的上下文中呈现,则 useInRouterContext 钩子返回 true ,否则
返回 false

5. useNavigationType()

1. 作用:返回当前的导航类型(用户是如何来到当前页面的)。
2. 返回值: POP PUSH REPLACE
3. 备注: POP 是指在浏览器中直接打开了这个路由组件(刷新页面)。

6. useOutlet()

1. 作用:用来呈现当前组件中渲染的嵌套路由。
2. 示例代码:
const result = useOutlet() 
console.log(result) 
// 如果嵌套路由没有挂载,则result为null 
// 如果嵌套路由已经挂载,则展示嵌套的路由对象

7. useResolvedPath

1. 作用:给定一个 URL 值,解析其中的: path search hash 值。

你可能感兴趣的:(前端,react,javascript)