Javascript 在用户登录或未登录时实现条件导航栏的策略
背景:我正在创建一个非常基本的应用程序,它具有4种不同的功能:注册、登录、搜索和创建内容。从现在起,我可以登录到用户并防止未经授权的用户进入受保护的路由。这显示在我的Javascript 在用户登录或未登录时实现条件导航栏的策略,javascript,reactjs,redux,react-router,react-router-dom,Javascript,Reactjs,Redux,React Router,React Router Dom,背景:我正在创建一个非常基本的应用程序,它具有4种不同的功能:注册、登录、搜索和创建内容。从现在起,我可以登录到用户并防止未经授权的用户进入受保护的路由。这显示在我的Protected.js组件中。然而,我正在努力找到一种方法,在我的App.js导航栏中有条件地显示登录/注销按钮 后续问题:我是否应该将身份验证逻辑从我的Login.js路径中移到我的主App.js组件中并向下传递状态?这不是效率很低吗,因为每次我呈现一个新视图时,App.js都会使用我的后端API执行另一次获取,以验证用户是否有
Protected.js
组件中。然而,我正在努力找到一种方法,在我的App.js
导航栏中有条件地显示登录/注销按钮
后续问题:我是否应该将身份验证逻辑从我的Login.js
路径中移到我的主App.js
组件中并向下传递状态?这不是效率很低吗,因为每次我呈现一个新视图时,App.js
都会使用我的后端API执行另一次获取,以验证用户是否有一个未过期的会话?这对一些人来说可能显得微不足道,但我很难思考如何有条件地高效地显示登录/注销按钮。我已经研究了上下文API,所以如果您觉得有必要,我愿意接受一些建议,但我对Redux并不熟悉(我一周前才开始做出反应)。我正在寻找经过深思熟虑的策略,因此如果您能尽最大努力提供完整和连贯的回答,我将不胜感激。我真的很感激
App.js
class App extends Component {
render() {
return(
<Router>
<div>
<Navbar bg="light" variant="light">
<Navbar.Brand href="#home">My Application</Navbar.Brand>
<Nav className="mr-auto">
<Link to="/signup" className="nav-link">Signup</Link>
<Link to="/login" className="nav-link">Login</Link>
<Link to="/feed" className="nav-link">Search</Link>
<Link to="/create-post" className="nav-link">Create</Link>
</Nav>
<Form inline>
<Button variant="outline-primary">Logout</Button>
</Form>
</Navbar>
</div>
<Switch>
<Route path = '/signup' component = {Signup} />
<Route path = '/login' component = {Login} />
<Route path = '/feed' component = {Feed} />
<ProtectedRoute path = '/create-post' component = {CreatePost} />
</Switch>
</Router>
)
}
}
class Login extends Component {
constructor(props) {
super(props)
this.state = {
username: "",
password: ""
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmitForm = this.handleSubmitForm.bind(this)
}
handleChange(event) {
//console.log(event.target.name)
this.setState({[event.target.name]: event.target.value})
}
handleSubmitForm() {
const user = {
username: this.state.username,
password: this.state.password
}
const url = 'http://localhost:9000/api/login'
fetch(url, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
})
.then((response) => response.json())
.then((data) => {
if (data.status === 1) {
this.props.history.push('/feed')
}
console.log(data)
})
.catch((error) => {
console.log('Error', error)
})
}
render() {
return (
<div>
<Card className="card-login" style={{ width: '18rem' }}>
<Card.Body>
<Card.Title>Login</Card.Title>
<Form>
<Form.Group>
<Form.Control placeholder ="Username"
name = "username"
value = {this.state.username}
onChange = {this.handleChange}/>
</Form.Group>
<Form.Group>
<Form.Control type ="password"
placeholder="Password"
name = "password"
value = {this.state.password}
onChange = {this.handleChange} />
</Form.Group>
<Button variant ="primary"
value="Submit"
onClick={this.handleSubmitForm}>Submit
</Button>
</Form>
</Card.Body>
</Card>
</div>)
}
}
class ProtectedRoute extends Component {
constructor(props) {
super(props)
this.state = {
isAuthenticated: false,
isLoading: true
}
this.isAuthenticated = this.isAuthenticated.bind(this)
}
componentDidMount() {
this.isAuthenticated()
}
isAuthenticated() {
const url = 'http://localhost:9000/api/auth'
fetch(url, {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type' : 'application/json'
}
})
.then((response) => response.text())
.then((data) => {
if (data === 'true') {
this.setState({
isAuthenticated: true,
isLoading: false
})
} else {
this.setState({
isAuthenticated: false,
isLoading: false
})
}
})
.catch((err) => {
console.log('Error', err)
})
}
render() {
const Component = this.props.component
if (this.state.isLoading === true) {
return (<div>Loading</div>)
}
return(
<Route render={(props) => this.state.isAuthenticated && !this.state.isLoading ? (<Component {...this.props}/>) : (<Redirect to ='/login' />)} />
)
}
}
显然需要全局状态,您可以在
App
组件中使用React-Context、Redux甚至set-auth-state、pass方法来更改状态,即setAuth
,作为Login
组件的道具
class App extends Component {
constructor(props) {
super(props);
this.setAuth = this.setAuth.bind(this);
this.state = {
isAuthenticated: false
};
}
setAuth(value) {
this.setState({
isAuthenticated: value
});
}
}/>
我是否应该将身份验证逻辑移出Login.js路径并
进入我的主App.js组件并传递状态?那不是吗
效率很低,因为每次渲染新视图时
App.js正在使用我的后端api执行另一次获取,以验证
用户是否有未过期的会话
您是指Protectedroute
组件中发生的逻辑吗?我会像你说的那样将其提取到App
组件中,因为在一个场景中
当您想进入
“/update post”
部分时,它会检查用户是否多次经过身份验证。谢谢您的详细回答。您给出的第一个响应是一个在子组件中修改应用程序状态的好例子。但是,关于您的第二个回答,我想确保我正确理解您:您是否建议我放弃ProtectedRoute
,并将所有获取身份验证逻辑从ProtectedRoute
移动到应用程序中?如果是这样的话,我的App
组件是否会在每次装载新组件时执行提取@Józef Podlecki如果您将请求放入componentDidMount
,然后更改状态,则是,它仍将再次执行获取。但是shouldComponentUpdate(nextProps)
起到了解救作用,在那里你可以做一个非常简单的谓词,它忽略isAuthenticated
prop change或者一直返回false
。这是公认的答案。感谢您提供反馈。@波德莱斯基
class App extends Component {
constructor(props) {
super(props);
this.setAuth = this.setAuth.bind(this);
this.state = {
isAuthenticated: false
};
}
setAuth(value) {
this.setState({
isAuthenticated: value
});
}