React Router 仅在刷新后渲染
我正在尝试使用 react redux 和 router 创建一个 web 应用程序,但我遇到了一个奇怪的行为,Router 只在刷新时呈现。 那是我的 App.js
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Router, Switch, Route, Link } from "react-router-dom";
import { ModalProvider } from './modal/modalContext';
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";
import Login from "./components/Login";
import Register from "./components/Register";
import Home from "./components/Home";
import Profile from "./components/Profile";
import BoardUser from "./components/BoardUser";
import BoardModerator from "./components/BoardModerator";
import BoardAdmin from "./components/BoardAdmin";
import DataService from "./services/data.service";
import { logout } from "./actions/auth";
import { clearMessage } from "./actions/message";
import { setDc } from "./actions/dc";
import { history } from "./helpers/history";
import simplidc_logo from "./images/dns-24px.svg"
import DetailedRackCard from './components/detailed_rack_card'
const App = () => {
const [showModeratorBoard, setShowModeratorBoard] = useState(false);
const [showAdminBoard, setShowAdminBoard] = useState(false);
const { user: currentUser } = useSelector((state) => state.auth);
const dispatch = useDispatch();
useEffect(() => {
history.listen((location) => {
dispatch(clearMessage()); // clear message when changing location
});
}, [dispatch]);
useEffect(() => {
if (currentUser) {
setShowModeratorBoard(currentUser.roles.includes("ROLE_MODERATOR"));
setShowAdminBoard(currentUser.roles.includes("ROLE_ADMIN"));
}
}, [currentUser]);
useEffect(() => {
DataService.getDevices().then(
(devicesResponse) =>{
DataService.getRacks().then(
(racksResponse) =>{
dispatch(setDc(DataService.getDc(racksResponse,devicesResponse)));
}
)
}
)
}, [dispatch]);
const logOut = () => {
dispatch(logout());
};
return (
<div>
<ModalProvider>
<Router history={history}>
<div>
<nav className="navbar navbar-expand navbar-dark bg-dark">
<Link to={"/"} className="navbar-brand">
SimpliDC
<img
alt=""
src={simplidc_logo}
width="30"
height="30"
/>
</Link>
<div className="navbar-nav mr-auto">
<li className="nav-item">
<Link to={"/home"} className="nav-link">
Home
</Link>
</li>
{showModeratorBoard && (
<li className="nav-item">
<Link to={"/mod"} className="nav-link">
Moderator Board
</Link>
</li>
)}
{showAdminBoard && (
<li className="nav-item">
<Link to={"/admin"} className="nav-link">
Admin Board
</Link>
</li>
)}
{currentUser && (
<li className="nav-item">
<Link to={"/user"} className="nav-link">
User
</Link>
</li>
)}
</div>
{currentUser ? (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/profile"} className="nav-link">
{currentUser.username}
</Link>
</li>
<li className="nav-item">
<a href="/login" className="nav-link" onClick={logOut}>
LogOut
</a>
</li>
</div>
) : (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/login"} className="nav-link">
Login
</Link>
</li>
<li className="nav-item">
<Link to={"/register"} className="nav-link">
Sign Up
</Link>
</li>
</div>
)}
</nav>
<input className="" type="text" placeholder="Type any vaule to search in the DC..."/>
<div className="container mt-3">
<Switch>
<Route exact path={["/", "/home"]} component={Home} />
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route exact path="/profile" component={Profile} />
<Route path="/user" component={BoardUser} />
<Route path="/mod" component={BoardModerator} />
<Route path="/admin" component={BoardAdmin} />
<Route path="/rack/:id" component={DetailedRackCard}/>
</Switch>
</div>
</div>
</Router>
</ModalProvider>
</div>
);
};
export default App;
我在查看 Router 组件上的 react dev tools 时发现发生了一些奇怪的事情。这是刷新后的状态位置:
我迫切需要帮助.... 是的,那是我整个应用程序中唯一的路由器。
谢谢!
<Router/>
的
state
来自您提供的
history
属性。您没有正确修改该
history
。错误的变异将在另一个文件中的某个位置。您似乎正在使用整个操作对象而不是仅使用
action.location
属性来调用
history.push()
。
将
<Router/>
组件与自定义
history
属性一起使用是一种高级设计模式,除非绝对必要,否则您通常要避免这种模式。我认为这里没有必要,至少对于这个特定文件中的代码来说没有必要。
我建议改用
<BrowserRouter/>
(或
<HashRouter/>
等)。如果这样做,您将需要其他方法来解决
history.listen
订阅(旁注:您想使用清理函数在组件卸载时停止监听)。
您可以使用
useEffect
钩子来响应您从
useLocation
钩子访问的位置的变化。
const location = useLocation();
useEffect(() => {
dispatch(clearMessage()); // clear message when changing location
}, [location, dispatch]);
如果您不想在第一次渲染时清除消息,您可以添加一些调度前进行额外检查。您可以使用
usePrevious
自定义钩子或类似钩子。在这里,我使用
useRef
来存储上一个位置。ref 的初始值是来自
useLocation
的
location
,因此在第一次渲染时它们将相等。
const location = useLocation();
const locRef = useRef(location);
useEffect(() => {
console.log(locRef.current, location);
// will be equal on first render
if (locRef.current !== location) {
dispatch(clearMessage());
}
locRef.current = location;
}, [location, dispatch]);
如果您愿意,可以修改它以仅查看
pathname
。