Reactjs 使用react router dom重新加载页面时出现问题
我使用Reactjs 使用react router dom重新加载页面时出现问题,reactjs,typescript,firebase,routes,react-router-dom,Reactjs,Typescript,Firebase,Routes,React Router Dom,我使用react-router-dom创建了一条专用路由并导航到不同的页面。然而,当我导航到一个页面并重新加载它时,它首先进入/login半秒钟,然后正确地重新加载页面。如何防止这种不必要的行为并改进我的路由 以下是我的路线: <Router> <Route path="/" component={() => !auth ? <Redirect to="/login
react-router-dom
创建了一条专用路由并导航到不同的页面。然而,当我导航到一个页面并重新加载它时,它首先进入/login
半秒钟,然后正确地重新加载页面。如何防止这种不必要的行为并改进我的路由
以下是我的路线:
<Router>
<Route
path="/"
component={() =>
!auth ? <Redirect to="/login" /> : <Redirect to={path} />
}
/>
<Route exact path="/home" component={Home} />
<Route exact path="/dashboard" component={Dashboard} />
<Route exact path="/login" component={RedirectPage} />
</Router>
这是App
组件:
import {
Route,
BrowserRouter as Router,
Link,
Redirect,
} from "react-router-dom";
import { Container, Button } from "@material-ui/core/";
import Login from "./Login";
import { useContext,useState } from "react";
import { UserContext } from "../App";
import { signOut } from "../Storage/Auth";
const Routes = () => {
const { auth, setAuth, logging } = useContext(UserContext);
const [path,setPath] = useState("/home")
const handleSignOut = () => {
signOut(setAuth);
console.log("Auth", auth);
};
const Home = () => {
console.log("Home");
return (
<Container>
<h1>Welcome</h1>
<Link to="/">
<Button onClick={handleSignOut}> Log Out</Button>
</Link>
<Link to="/dashboard">
<Button> Dash</Button>
</Link>
</Container>
);
};
const Dashboard = () => {
setPath("/dashboard")
console.log("Dash");
return (
<Container>
<Link to="/home">
<Button> HOME</Button>
</Link>
<h1>Dashboard</h1>
</Container>
);
};
const RedirectPage = () => {
if (!logging) {
return <div></div>;
} else {
return <Login />;
}
};
return (
<Router>
<Route
path="/"
component={() =>
!auth ? <Redirect to="/login" /> : <Redirect to={path} />
}
/>
<Route exact path="/home" component={Home} />
<Route exact path="/dashboard" component={Dashboard} />
<Route exact path="/login" component={RedirectPage} />
</Router>
);
};
export { Routes };
import { useEffect } from "react";
import { Routes } from "./Routing/Routes";
import "./App.css";
import { Container } from "@material-ui/core/";
import initFirebase from "./Storage/Secret";
import { useState, createContext } from "react";
import { onAuthChange } from "./Storage/Auth";
export const UserContext = createContext<any>(null);
function App() {
const [user, setUser] = useState(null);
const [auth, setAuth] = useState<string | null>("");
const [logging, setLogging] = useState(null)
useEffect(() => {
initFirebase();
}, []);
useEffect(() => {
onAuthChange(setAuth,setLogging);
}, [auth]);
return (
<UserContext.Provider value={{ user, setUser, auth,setAuth,logging }}>
<div className="App">
<Container>
<Routes />
</Container>
</div>
</UserContext.Provider>
);
}
export default App;
最后,完整的代码在
如果您有任何建议,我们将不胜感激。我建议您早点进行身份验证。这样,只有当auth中有内容时,才能渲染路由本身。我认为您的示例也缺少Switch语句,而Switch语句通常很有用
{!啊(
) : (
)}
通常,您希望某种“加载”或“不确定”状态既不表示已验证也不表示未验证。您可以使用第三个“状态”来保持UI,然后再根据身份验证以某种方式呈现
由于auth
逻辑解析为布尔值true
|false
const onAuthChange = (setState, setLoading) => {
auth().onAuthStateChanged((u) => {
if (!u) {
console.log(u);
setLoading(true);
} else {
setState(u);
setLoading(false);
}
});
};
您可以使用这样一个事实,即初始的auth
状态不是这两种状态。我建议使用null
const [auth, setAuth] = useState<string | null>(null);
这里请注意,我还切换到了渲染
属性,组件
属性用于连接实际的组件。他们的待遇有点不同。您可以阅读有关路由渲染方法差异的信息
完整的路由器示例:
<Router>
<Switch>
<Route path="/home" component={Home} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/login" component={RedirectPage} />
<Route
path="/"
render={() => {
if (auth === null) return null;
return <Redirect to={auth ? path : "/login" />;
}}
/>
</Switch>
</Router>
{
if(auth==null)返回null;
返回;
}}
/>
请注意,我还包括了
开关
组件,并对路由进行了重新排序,以便在不太具体的路径之前列出更具体的路径。这允许您从所有路由中删除不必要的精确的道具,因为交换机
以独占方式呈现路由(而不是像路由器
那样以包含方式呈现路由)。我终于设法解决了这个问题。现在,重新加载工作正常,安全性也得到了例外的实现。这是我最后的路由器
:
<Router>
<Route
path="/"
render={() =>
logging ? <Redirect to={"/login"} /> : <Redirect to={path} />
}
/>
<Route exact path="/" render={() => auth && <Home />} />
<Route exact path="/dashboard" render={() => auth && <Dashboard />} />
<Route exact path="/login" component={Login} />
</Router>
日志记录?:
}
/>
验证&&}/>
验证&&}/>
这就是组件现在的样子
import {
Route,
BrowserRouter as Router,
Link,
Redirect
} from "react-router-dom";
import { Container, Button } from "@material-ui/core/";
import Login from "./Login";
import { useContext, useState, useEffect } from "react";
import { UserContext } from "../App";
import { signOut } from "../Storage/Auth";
const Routes = () => {
const { auth, setAuth, logging } = useContext(UserContext);
const handleSignOut = () => {
signOut(setAuth);
console.log("Auth", auth);
};
const pathname = window.location.pathname;
const [path, setPath] = useState(pathname);
useEffect(() => {
console.log(path);
path === "/login" && setPath("/");
path !== "/" && path !== "/dashboard" && setPath("/");
}, [auth]);
const Home = () => {
console.log("Home");
return (
<Container>
<h1>Welcome</h1>
<Link to="/">
<Button onClick={handleSignOut}> Log Out</Button>
</Link>
<Link to="/dashboard">
<Button> Dash</Button>
</Link>
</Container>
);
};
const Dashboard = () => {
console.log("Dash");
return (
<Container>
<Link to="/">
<Button> HOME</Button>
</Link>
<h1>Dashboard</h1>
</Container>
);
};
return (
<Router>
<Route
path="/"
render={() =>
logging ? <Redirect to={"/login"} /> : <Redirect to={path} />
}
/>
<Route exact path="/" render={() => auth && <Home />} />
<Route exact path="/dashboard" render={() => auth && <Dashboard />} />
<Route exact path="/login" component={Login} />
</Router>
);
};
export { Routes };
导入{
路线,,
BrowserRouter作为路由器,
链接
重新使用
}从“反应路由器dom”;
从“@material ui/core/”导入{Container,Button}”;
从“/Login”导入登录名;
从“react”导入{useContext,useState,useEffect};
从“./App”导入{UserContext};
从“./Storage/Auth”导入{signOut};
常数路由=()=>{
const{auth,setAuth,logging}=useContext(UserContext);
常量handleSignOut=()=>{
签出(setAuth);
console.log(“Auth”,Auth);
};
const pathname=window.location.pathname;
const[path,setPath]=useState(路径名);
useffect(()=>{
console.log(路径);
路径==“/login”&&setPath(“/”;
路径!=“/”&&path!=“/dashboard”&&setPath(“/”);
},[auth]);
常量Home=()=>{
控制台日志(“主页”);
返回(
欢迎
注销
猛冲
);
};
常量仪表板=()=>{
控制台日志(“破折号”);
返回(
家
仪表板
);
};
返回(
日志记录?:
}
/>
验证&&}/>
验证&&}/>
);
};
出口{路线};
感谢@Richard和@Drew的友好支持。您能否共享您的私有路由组件,以便我们了解它在解析身份验证状态时的功能,以及您使用私有路由的代码?我怀疑您实际上没有实现PrivateRoute
组件,尽管从您的代码片段判断。您还可以包括您的UserContext
代码吗?如果您需要实现身份验证流的帮助,请查看身份验证工作流示例。@drewerese我更新了问题,并将此链接添加到完整的repo中auth
状态的正常值是多少?您可以从与“已验证”或“未验证”状态不同的初始状态开始,然后等待该值不等于初始状态。@drewrese我添加了验证逻辑。谢谢你的建议。我将试验一下。我正在试验你的建议,以使它发挥作用。非常感谢。
<Router>
<Switch>
<Route path="/home" component={Home} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/login" component={RedirectPage} />
<Route
path="/"
render={() => {
if (auth === null) return null;
return <Redirect to={auth ? path : "/login" />;
}}
/>
</Switch>
</Router>
<Router>
<Route
path="/"
render={() =>
logging ? <Redirect to={"/login"} /> : <Redirect to={path} />
}
/>
<Route exact path="/" render={() => auth && <Home />} />
<Route exact path="/dashboard" render={() => auth && <Dashboard />} />
<Route exact path="/login" component={Login} />
</Router>
import {
Route,
BrowserRouter as Router,
Link,
Redirect
} from "react-router-dom";
import { Container, Button } from "@material-ui/core/";
import Login from "./Login";
import { useContext, useState, useEffect } from "react";
import { UserContext } from "../App";
import { signOut } from "../Storage/Auth";
const Routes = () => {
const { auth, setAuth, logging } = useContext(UserContext);
const handleSignOut = () => {
signOut(setAuth);
console.log("Auth", auth);
};
const pathname = window.location.pathname;
const [path, setPath] = useState(pathname);
useEffect(() => {
console.log(path);
path === "/login" && setPath("/");
path !== "/" && path !== "/dashboard" && setPath("/");
}, [auth]);
const Home = () => {
console.log("Home");
return (
<Container>
<h1>Welcome</h1>
<Link to="/">
<Button onClick={handleSignOut}> Log Out</Button>
</Link>
<Link to="/dashboard">
<Button> Dash</Button>
</Link>
</Container>
);
};
const Dashboard = () => {
console.log("Dash");
return (
<Container>
<Link to="/">
<Button> HOME</Button>
</Link>
<h1>Dashboard</h1>
</Container>
);
};
return (
<Router>
<Route
path="/"
render={() =>
logging ? <Redirect to={"/login"} /> : <Redirect to={path} />
}
/>
<Route exact path="/" render={() => auth && <Home />} />
<Route exact path="/dashboard" render={() => auth && <Dashboard />} />
<Route exact path="/login" component={Login} />
</Router>
);
};
export { Routes };