Я создаю приложение React Router и изучаю аутентификацию.Вот некоторые части:
Компонент входа (login.jsx)
- проверяет подлинность учетных данных пользователя на серверной части
- устанавливает токен аутентификации в локальном хранилище
- возвращает данные пользователя
- устанавливает состояние с данными
- передает состояние компоненту администратора
компонент администратора (admin.jsx)
- защищен частным маршрутом (см. Privateroute.jsx)
- в основном компонент контейнера
- передает данные пользователя и отображает другие компоненты, которые отображают / редактируют данные
Кнопка аутентификации на навигационной панели (authbutton.jsx)
- проверяет, вошел ли пользователь в систему, и отображает кнопку «вход» или «выход»
- , если вошел в систему,также отображает кнопку «Мои сообщения», которая перенаправляет к администратору
Все хорошо работает от входа к администратору.Моя проблема в том, что, когда я щелкаю на странице администратора (например, на домашней странице), а затем нажимаю кнопку «Мои сообщения», он перенаправляется на страницу «Администратор» и знает, что я вошел в систему, но данные пользователя больше недоступны.Раньше, исходя из компонента входа в систему, данные пользователя были в this.props.location.state.me
.
Я застрял, потому что я пытаюсь перенаправить на Admin из двух разных компонентов, и я никогда не делал этого раньше.Кроме того, я чувствую, что в настройке аутентификации есть решение, которое мне не хватает.
Другие идеи:
Должен ли я условно устанавливать состояние в Admin при передаче данных пользователя?
Должен ли я хранить данные в локальном хранилище в браузере, как я делаю с токеном аутентификации?
Я попытался извлечь данные, установив состояние в Admin с помощью componentDidMount
, но он не рендерился повторно, поэтому я прочитал, чтобы использовать componentWillReceiveProps
, но это устарело и заменено на getDerivedStateFromProps
.Не могу понять это.
login.jsx
import React, { Component, Fragment } from 'react';
import * as userService from '../../services/user';
import { Redirect } from 'react-router-dom';
import IndeterminateProgress from '../utilities/indeterminateprogress';
import Nav from '../home/nav';
class Login extends Component {
constructor(props) {
super(props);
this.state = {
redirectToReferrer: false,
email: '',
password: '',
feedbackMessage: '',
checkingLogin: true,
me: ''
};
}
componentDidMount() {
userService.checkLogin()
.then((loggedIn) => {
if (loggedIn) {
this.setState({ redirectToReferrer: true, checkingLogin: false });
} else {
this.setState({ checkingLogin: false });
}
});
}
login(e) {
e.preventDefault();
userService.login(this.state.email, this.state.password)
.then((meData) => {
this.setState({ redirectToReferrer: true, me: meData })
})
.catch((err) => {
if (err.message) {
this.setState({ feedbackMessage: err.message });
}
});
}
handleEmailChange(value) {
this.setState({ email: value });
}
handlePasswordChange(value) {
this.setState({ password: value });
}
render() {
const { from } = this.props.location.state || { from: { pathname: '/admin', state: { ...this.state } } };
const { redirectToReferrer, checkingLogin } = this.state;
if (checkingLogin) {
return <IndeterminateProgress message="Checking Login Status..." />;
}
if (redirectToReferrer) {
return (
<Redirect to={from} />
);
}
return (
<Fragment>
<Nav />
<h2 className="heading center">Login to continue</h2>
<form className="center" onSubmit={(e) => this.login(e)}>
<div className="form-group">
<input
placeholder="Email"
id="email"
className="col-3"
type="email"
onChange={(e) => this.handleEmailChange(e.target.value)}
required
/>
</div>
<div className="form-group">
<input
placeholder="Password"
id="password"
className="col-3"
type="password"
onChange={(e) => this.handlePasswordChange(e.target.value)}
required
/>
</div>
{this.state.feedbackMessage ? (
<p>{this.state.feedbackMessage}</p>
) : null}
<input type="submit" value="Login" className="btn btn-info btn-sm" />
</form>
</Fragment>
);
}
}
export { Login };
admin.jsx
import React, { Component } from 'react';
import Nav from '../home/nav';
import AdminBlogContainer from './adminblogcontainer'
import { BrowserRouter as Router, Link } from 'react-router-dom';
const Admin = (props) => {
return (
<div className="flexcol center">
<Nav />
<h1 className="heading">Your Blog Posts</h1>
<AdminBlogContainer {...props.location.state.me} />
<Link to={{
pathname: '/write',
state: { ...props.location.state.me }
}}
className="btn btn-outline-secondary mt-4"
>Create a New Blog Post</Link>
</div>
)
}
export { Admin };
privateroute.jsx
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { isLoggedIn } from '../../services/user';
const PrivateRoute = (props) => {
const Component = props.component;
const propsToPass = Object.assign({}, props);
delete propsToPass.component;
return (
<Route {...propsToPass} render={props => (
isLoggedIn() ? (
<Component {...props} />
) : (
<Redirect to={{
pathname: '/login',
state: { from: props.location }
}} />
)
)} />
);
};
export { PrivateRoute }
кнопка авторизации.JSX
import React from 'react';
import { Link } from 'react-router-dom';
import { isLoggedIn } from '../../services/user';
const AuthButton = (props) => {
if (isLoggedIn()) {
return (
<div>
<Link className="btn btn-info m-1" to="/logout">Logout</Link>
<Link className='btn btn-info m-1' to={{
pathname: '/admin',
// state: { ...this.state }
}}
>My Posts</Link>
</div>
);
} else {
return (
<div>
<Link className="btn btn-info m-1" to="/login">Login</Link>
<Link className="btn btn-info m-1" to="/register">Register</Link>
</div>
)
}
};
export { AuthButton };