Javascript 如何在React.JS中更改登录/注销时的导航栏文本?
我的项目中有一个导航栏,我从Javascript 如何在React.JS中更改登录/注销时的导航栏文本?,javascript,reactjs,react-router,react-hooks,Javascript,Reactjs,React Router,React Hooks,我的项目中有一个导航栏,我从App.js内部调用它。根据我是否登录,我希望呈现NavBar的不同视图。如果登录,我希望导航栏有一个注销按钮。如果注销,我希望导航栏上有登录按钮。我使用localStorage中的令牌检查我是否登录。登录时,令牌出现在localStorage中。注销时/登录前,localStorage中没有令牌密钥。我将此令牌作为状态传递给NavBar,如图所示: export default function App() { const [loggedIn, setLogg
App.js
内部调用它。根据我是否登录,我希望呈现NavBar
的不同视图。如果登录,我希望导航栏
有一个注销按钮。如果注销,我希望导航栏上有登录按钮。我使用localStorage
中的令牌检查我是否登录。登录时,令牌出现在localStorage
中。注销时/登录前,localStorage
中没有令牌密钥。我将此令牌作为状态传递给NavBar
,如图所示:
export default function App() {
const [loggedIn, setLoggedIn] = useState(localStorage.getItem("token"));
return (
<div>
<Router>
<Navbar isAuth={loggedIn} />
<Route exact path="/" exact component={Home} />
<Route path="/login" component={Login} />
<PrivateRoute path="/dashboard" component={Dashboard} />
</Router>
</div>
);
}
问题是,NavBar
不会在我登录后立即更新自身。我必须手动刷新页面才能呈现新的NavBar
。同样,在注销时,它也不更新自身,只在手动刷新时更新。问题是什么?如何解决 您还需要添加。从文件中:
渲染与该位置匹配的第一个子对象
的独特之处在于它以独占方式呈现路由。相反,每个与位置匹配的
都以包含方式呈现
如下所示:
<Router>
<Switch>
<Navbar isAuth={loggedIn} />
<Route exact path="/" exact component={Home} />
<Route path="/login" component={Login} />
<PrivateRoute path="/dashboard" component={Dashboard} />
</Switch>
</Router>
请在此进一步阅读:
我希望这有帮助 如果更改localStorage中
标记的值,则应用程序的状态不会更新
您需要确保更新状态,如果有帮助,我已经添加了一个。我找到了一个简单的解决方案:
使用componentDidMount()或useEffect()函数,该函数将在加载导航栏页面时自动呈现。
在该函数中,使用setInterval()函数连续检索身份验证状态(例如,间隔为5000)。这将持续刷新导航栏,并立即更改按钮。
我想您必须将auth检查放在NavBar组件本身中,而不是使用道具。我把我想更改的特定按钮放在一个名为NavBarUser的单独组件中,该组件将“login | signup”更改为“logout”,并包含一个用户化身。然后,我将该组件插入导航栏本身的适当位置。
这就是我的代码的样子:
```
从“React”导入React,{useState,useffect};
从“./Avatar”导入化身;
从“react Router dom”导入{BrowserRouter as Router,Link}
const NavBarUser = () => {
const [user, setUser] = useState({});
useEffect(() => {
{ /*
setInterval was used in order to refresh the page constantly
in order to have the "logout" button show immediately in place of
"login", as soon as user logs out.
*/}
setInterval(() => {
const userString = localStorage.getItem("user");
const user = JSON.parse(userString);
setUser(user);
}, [])
}, 5000);
const logout = () => {
return localStorage.removeItem("user");
}
if (!user) {
return (
<div className="navbar-nav ml-auto">
<Link to="/login" className="nav-item nav-link">Login</Link> <span
className="nav-item nav-link">|</span> <Link to="/SignUp" className="nav-item nav-
link">Sign Up</Link>
</div>
)
}
if (user) {
return (
<div className="navbar-nav ml-auto">
<Link to="/" className="nav-item nav-link" onClick={logout}>Logout</Link>
<Avatar img="/images/Eat-healthy.jpg" />
</div>
)
}
}
export default NavBarUser;
```
const NavBarUser=()=>{
const[user,setUser]=useState({});
useffect(()=>{
{ /*
setInterval用于不断刷新页面
为了让“注销”按钮立即显示在
“登录”,一旦用户注销。
*/}
设置间隔(()=>{
const userString=localStorage.getItem(“用户”);
const user=JSON.parse(userString);
setUser(用户);
}, [])
}, 5000);
常量注销=()=>{
返回localStorage.removietem(“用户”);
}
如果(!用户){
返回(
登录|注册
)
}
如果(用户){
返回(
注销
)
}
}
导出默认NavBarUser;
```
以下是我解决此问题的方法:
首先,我在我的App
类中创建了一个isLoggedIn
状态。我给了它一个componentDidMount()
方法,该方法将在应用程序启动时从cookie获取登录状态。然后我创建了globalgoin
和globalgout
方法作为箭头函数,它们相应地将isLoggedIn
状态设置为true或false。我将Nav
组件isLoggedIn
状态作为道具传递,并传递Login
和Nav
路由globalLogin
和globalout
方法。然后,可以使用this.props.globallout()从Login
或Nav
调用这些方法
或this.props.globalwin()代码>
这是我的App.js
的简化版本
class App extends Component {
constructor(props){
super(props);
this.state = {
isLoggedIn: false,
}
}
componentDidMount() {
const token = Cookie.get("token") ? Cookie.get("token") : null;
if (token) {
this.setState({ "isLoggedIn": true });
}
}
globalLogin = () => {
this.setState({ "isLoggedIn": true });
}
globalLogout = () => {
this.setState({ "isLoggedIn": false });
}
render() {
return (
<Router>
<div className="App">
<Nav isLoggedIn={this.state.isLoggedIn} globalLogout={this.globalLogout}/>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/login" exact>
<Login globalLogin={this.globalLogin}/>
</Route>
</Switch>
</div>
</Router>
);
}
}
类应用程序扩展组件{
建造师(道具){
超级(道具);
此.state={
伊斯洛格丁:错,
}
}
componentDidMount(){
const token=Cookie.get(“token”)?Cookie.get(“token”):null;
如果(令牌){
this.setState({“isLoggedIn”:true});
}
}
珠蛋白=()=>{
this.setState({“isLoggedIn”:true});
}
GlobalOut=()=>{
this.setState({“isLoggedIn”:false});
}
render(){
返回(
);
}
}
编辑:在上面的登录模块中使用history.push不起作用,所以我添加了一个中介来处理道具
render() {
const LoginIntermediate = (props) => {
return (
<Login {...props} globalLogin={this.globalLogin}/>
)
}
return (
<Router>
<div className="App">
<Nav isLoggedIn={this.state.isLoggedIn} globalLogout={this.globalLogout}/>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/login" exact component={LoginIntermediate} />
</Switch>
</div>
</Router>
);
}
render(){
const LoginIntermediate=(道具)=>{
返回(
)
}
返回(
);
}
使用switch停止呈现我的其他组件,如Home,在点击它们的URL时登录。我认为问题在于应用程序和导航栏之间的状态传递。按钮在导航栏内部,而不是在代码演示的外部。然后,您需要从父级发送一个函数作为道具,单击按钮时您将调用该函数。这样可以控制父类中的状态。看,这应该会有帮助。
render() {
const LoginIntermediate = (props) => {
return (
<Login {...props} globalLogin={this.globalLogin}/>
)
}
return (
<Router>
<div className="App">
<Nav isLoggedIn={this.state.isLoggedIn} globalLogout={this.globalLogout}/>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/login" exact component={LoginIntermediate} />
</Switch>
</div>
</Router>
);
}