[英]Strategies to implementing a conditional Navbar if a user is logged in or not
Background : I am creating a very basic application with 4 different capabilities: Signup, Login, Searching, and Creating content.背景:我正在创建一个具有 4 种不同功能的非常基本的应用程序:注册、登录、搜索和创建内容。 As of right now, I can log in to users and prevent unauthorized users from going to protected routes.截至目前,我可以登录用户并防止未经授权的用户进入受保护的路线。 This is shown below in my Protected.js
component.这在我的Protected.js
组件中显示如下。 However, I am struggling to figure out a way to also conditionally display a login/logout button in my navigation bar located in my App.js
.但是,我正在努力想办法在位于我的App.js
的导航栏中有条件地显示登录/注销按钮。
Followup Questions : Should I move the authentication logic out of my Login.js
route and into my main App.js
component and pass the state down?后续问题:我应该将身份验证逻辑从我的Login.js
路由中移到我的主App.js
组件中,然后将 state 向下传递吗? Wouldn't that be very inefficient, because every time I am rendering a new view, the App.js
is performing another fetch with my backend API to verify if the user has a non-expired session?这不是非常低效吗,因为每次我渲染新视图时, App.js
都会使用我的后端 API 执行另一次提取,以验证用户是否有未过期的 session? This might appear trivial to some, but I am having a difficult time wrapping my head around how to conditionally show a login/logout button efficiently.这对某些人来说可能看起来微不足道,但我很难理解如何有条件地有效地显示登录/注销按钮。 I have looked into Context API, so I would be open to some advice down that route if you feel necessary, but I am not familiar with Redux( I just began to React a week ago ).我已经查看了上下文 API,所以如果你觉得有必要,我愿意接受一些建议,但我不熟悉 Redux(我一周前才开始 React )。 I am looking for well-thought-out strategies, so I would greatly appreciate it if you could do your best to provide complete and coherent responses.我正在寻找经过深思熟虑的策略,因此如果您能尽最大努力提供完整和连贯的回复,我将不胜感激。 I really appreciate it.对此,我真的非常感激。
App.js应用程序.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>
)
}
}
Login.js登录.js
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>)
}
}
Protectedroute.js受保护的路由.js
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' />)} />
)
}
}
api.js (Express Backend) api.js(快速后端)
router.post('/login', function(req,res,next) {
const query1 = "SELECT * FROM users WHERE username = TRIM(?) AND pass = TRIM(?)"
database.query(query1, [req.body.username, req.body.password])
.then((result) => {
if (result.length) {
if (req.session.username) {
res.json({'message': 'You are already logged in', 'status': 0})
} else {
req.session.username = req.body.username
res.json({'message': 'You have successfully logged in', 'status': 1})
}
} else {
if (req.session.username) {
res.json({'message': 'You are already logged in', 'status': 0})
} else {
res.json({'message': 'Incorrect Credentials', 'status': 0})
}
}
}).catch((err) => res.send(err))
})
router.get('/auth', (req, res, next) => {
if (req.session.username) {
res.send(true)
} else {
res.send(false)
}
})
Well there is clear need for the global state and you can use React Context, Redux or even set auth state in App
component, pass methods, which change state ie. Well there is clear need for the global state and you can use React Context, Redux or even set auth state in App
component, pass methods, which change state ie. setAuth
, as props to Login
component. 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
});
}
<Route path='/login' component={() => <Login setAuth={this.setAuth} />} />
Should I move the authentication logic out of my Login.js route and into my main App.js component and pass the state down?我应该将身份验证逻辑从我的 Login.js 路由中移到我的主 App.js 组件中,然后将 state 向下传递吗? Wouldn't that be very inefficient, because every time I am rendering a new view, the App.js is performing another fetch with my backend api to verify if the user has a non-expired session?这不是非常低效吗,因为每次我渲染新视图时,App.js 都会使用我的后端 api 执行另一次提取,以验证用户是否有未过期的 session?
Did you mean the logic which happens in Protectedroute
component?您是指Protectedroute
组件中发生的逻辑吗? I would extract that to App
component as you said because in a scenario正如您所说,我会将其提取到App
组件中,因为在一个场景中
<ProtectedRoute path = '/create-post' component = {CreatePost} />
<ProtectedRoute path = '/post-list' component = {PostList} />
<ProtectedRoute path = '/update-post' component = {UpdatePost} />
It would check if user is authenticated multiple times when you want to get to '/update-post'
section.当您想要进入'/update-post'
部分时,它会检查用户是否经过多次身份验证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.