Фон : я создаю очень простое c приложение с 4 различными возможностями: регистрация, вход в систему, поиск и создание контента. На данный момент я могу входить в систему пользователей и предотвращать несанкционированный доступ пользователей к защищенным маршрутам. Это показано ниже в моем Protected.js
компоненте. Однако я изо всех сил пытаюсь найти способ также условно отображать кнопку входа / выхода из системы на панели навигации, расположенной в моем App.js
.
Контрольные вопросы : Должен ли я переместить логи аутентификации c с моего маршрута Login.js
в мой основной компонент App.js
и передать состояние вниз? Разве это не было бы очень неэффективно, потому что каждый раз, когда я рендерил новое представление, App.js
выполняет другую выборку с моим API бэкэнда, чтобы проверить, есть ли у пользователя сеанс с истекшим сроком действия? Для некоторых это может показаться тривиальным, но мне трудно обдумать, как эффективно отобразить кнопку входа / выхода из системы. Я изучил Context API, поэтому я буду готов дать несколько советов по этому пути, если вы сочтете это необходимым, но я не знаком с Redux ( Я только начал React неделю a go). Я ищу хорошо продуманные стратегии, поэтому я был бы очень признателен, если бы вы приложили все усилия, чтобы предоставить полные и последовательные ответы. Я очень ценю это.
Приложение. 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>
)
}
}
Вход. 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
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)
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)
}
})