整理了一下新版的变化以及遇到的坑的解决办法,最后也会分享将网站及接口部署的方式。
千锋前端-React全家桶_React项目全球新闻发布管理系统
https://www.bilibili.com/video/BV1fw411d7R5
P4
反向代理 setupProxy.js
改为:
// setupProxy.js
const {
createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'https://i.maoyan.com',
changeOrigin: true,
})
);
};
App.js 中 axios 请求地址改为:
// App.js
useEffect(() => {
axios.get("/api/mmdb/movie/v3/list/hot.json?ct=%E7%B9%81%E6%98%8C%E5%8C%BA&ci=774&channelId=4")
.then((res) => console.log(res.data));
}, []);
因为我没有看到视频中用的 m.maoyan.com/ajax
那个地址,所以我自己抓了一个,反正是练习用的就不必那么讲究了,测试一下 middleware 能不能使就行。
P5
15 分处
HashRouter
里面包Switch
会出错,请改为包Routes
(Routes 和 Switch 的功用是一样的,都能做到精准匹配)Route
的 component 属性改为element
,并且 element 中请使用<>
包裹组件名称
// IndexRouter.js
import React from "react";
import {
HashRouter, Routes, Route } from "react-router-dom";
import Login from "../views/login/Login";
import NewsSandBox from "../views/newssandbox/NewsSandBox";
export default function IndexRouter () {
return (
<HashRouter>
<Routes>
<Route path="/login" element={
<Login/>} />
<Route path="/" element={
<NewsSandBox/>} />
</Routes>
</HashRouter>
);
};
20 分处重定向部分
For react-router-dom v6, simply replace Redirect with Navigate
所以我们需要将 Redirect 改为 Navigate,并且一样使用的是 element
而不是 render
<Route path="/*" element={
localStorage.getItem("token") ? <NewsSandBox/> : <Navigate to="/login"/>} />
P6
14 分处,一样将所有 Switch 改为 Routes
, component 改为 element
,Redirect 改为 Navigate
:
//NewsSandBox.js
<Routes>
<Route path="home" element={
<Home />} />
<Route path="user-manage/list" element={
<UserList />} />
<Route path="right-manage/role/list" element={
<RoleList />} />
<Route path="right-manage/right/list" element={
<RightList />} />
<Route path="/" element={
<Navigate replace from="/" to="home"/>} />
<Route path="/*" element={
<NoPermission/>} />
</Routes>
并且要记住的是 Navigate
只能包裹在 Route
中,Routes
中只能有 Route
或者 Fragment
。
P11
使用 withRouter 会报错:
‘withRouter’ is not exported from ‘react-router-dom’.
因为 V6 之后没有 withRouter
了,所以直接改用 useNavigate
会更方便,完整的 Code 我直接放出来吧:
import React from "react";
import {
Layout, Menu } from "antd";
import {
UserOutlined, HomeOutlined, CrownOutlined } from "@ant-design/icons";
import SubMenu from "antd/lib/menu/SubMenu";
import {
useNavigate } from "react-router";
const {
Sider } = Layout;
const menuList = [
{
key: "/home",
title: "首页",
icon: <HomeOutlined />,
},
{
key: "/user-manage",
title: "用户管理",
icon: <UserOutlined />,
children: [
{
key: "/user-manage/list",
title: "用户列表",
icon: <UserOutlined />,
},
],
},
{
key: "/right-manage",
title: "权限管理",
icon: <CrownOutlined />,
children: [
{
key: "/right-manage/role/list",
title: "角色列表",
icon: <CrownOutlined />,
},
{
key: "/right-manage/right/list",
title: "权限列表",
icon: <CrownOutlined />,
},
],
},
];
export default function SideMenu({
collapsed }) {
let navigate = useNavigate();
// Menu
const renderMenu = (menuList) => {
return menuList.map((item) => {
if (item.children) {
return (
<SubMenu key={
item.key} icon={
item.icon} title={
item.title}>
{
renderMenu(item.children)}
</SubMenu>
);
}
return (
<Menu.Item
key={
item.key}
icon={
item.icon}
onClick={
() => navigate(item.key)}
>
{
item.title}
</Menu.Item>
);
});
};
return (
<Sider trigger={
null} collapsible collapsed={
collapsed}>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={
["1"]}>
{
renderMenu(menuList)}
</Menu>
</Sider>
);
}
P15
props.location.pathname
可以用 useLocation 钩子取代,与 props.location 是一样的用法:
import {
useNavigate, useLocation } from "react-router";
// ...
let location = useLocation();
const selectKeys = [location.pathname]; // ex: ['/home']
const openKeys = ["/" + location.pathname.split("/")[1]];
// ...
<Menu theme="dark" mode="inline" selectedKeys={
selectKeys} defaultOpenKeys={
openKeys}>
{
renderMenu(menu)}
</Menu>
P17
直接写 res.data[0].children = ""
的话一旦 array 内容顺序有所变更就会错误,因此建议透过遍历的方式寻找 children 长度为 0 的元素,将它改为空字串。
useEffect(() => {
axios.get("http://localhost:8000/rights?_embed=children")
.then((res) => {
res.data.forEach((item) => item.children?.length === 0 ? item.children = "" : item.children);
setDataSource(res.data);
})
}, []);
P18
个人认为删除后页面要会 auto refresh,所以我改写了一下,这样只要删除权限时就会修改 refresh 的状态,而 refresh 状态一变更就会重新 call API 获取数据。
// RightList.js
const [dataSource, setDataSource] = useState([]);
const [refresh, setRefresh] = useState(false);
useEffect(() => {
axios.get("http://localhost:8000/rights?_embed=children").then((res) => {