Как useEffect вызывает новый рендер компонента?
Использую реакт-роут. Вопрос простой и сложный одновременно. Есть страничка с формой авторизации и навбар с защитой роутов. При не авторизированном пользователе в навбаре 2 ссылки, при авторизированном - 4. Теперь самое интересное - когда пользователь авторизируется навбар перерисовывается и показывает 4 ссылки, отлично. Но пользователь остаётся на страничке входа, как сделать редирект? Второе - когда пользователь выходит из системы навбар не перерисовывается и приходится нажимать на F5 что бы увидеть 2 ссылки. GitHub
навбар:
export function Navigbar() {
const [currentUser, setCurrentUser] = useState(undefined);
useEffect(() => {
Authentication();
});
function Authentication() {
setCurrentUser(localStorage.getItem('userToken'));
console.log(currentUser);
}
function LogOut() {
localStorage.removeItem('userToken');
console.log('deleted:' + localStorage.getItem('userToken'))
}
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<a className="navbar-brand" href="/">Control panel</a>
<button className="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav mr-auto">
{currentUser ? (
<div className="container">
<li className="nav-item ">
<Link className="nav-link" to="/additem">Add item</Link>
</li>
<li className="nav-item ">
<Link className="nav-link" to="/edititem">Edit item</Link>
</li>
<li className="nav-item ">
<Link className="nav-link" to="/deleteitem">Delete item</Link>
</li>
<li className="nav-item ">
<Link className="nav-link" to="/" onClick={LogOut}>
<span className="fas fa-sign-out-alt"/>
</Link>
</li>
</div>
) : (
<div className="container">
<li className="nav-item">
<Link className="nav-link" to="/">
<span className="fas fa-sign-in-alt"/>
</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/listOfItem">List of items</Link>
</li>
</div>
)}
</ul>
</div>
</nav>
)
}
форма логина:
export function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
useEffect(() => {
getToken();
});
function onChangeUsername(e) {
setUsername(e.target.value)
}
function onChangePassword(e) {
setPassword(e.target.value)
}
function getToken() {
console.log(username, password);
const token = Date.now().toString();
if (username && password) {
localStorage.setItem('userToken', JSON.stringify(token))
}
console.log(localStorage.getItem('userToken'))
}
return (
<div className="col-md-12">
<div className="card card-container">
<form onSubmit={getToken} noValidate>
<span className="fas fa-sign-in-alt"/>
<div className="form-group">
<label htmlFor="username">Username</label>
<input type="text" className="form-control"
name="username"
value={username}
onChange={onChangeUsername}
placeholder="Login"
required
/>
<div className="invalid-feedback">
Wrong username
</div>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
name="password"
value={password}
onChange={onChangePassword}
placeholder="Password"
required
/>
<div className="invalid-feedback">
Wrong password
</div>
</div>
<div className="form-group">
<button className="btn btn-primary" type="submit">
Submit form
</button>
</div>
</form>
</div>
</div>
)
}
Ответы (1 шт):
Moжно не делать отдельный роут на логин, а как-то:
<LogInDialogOrProtectedContent content={ grants => ....SomeSecretList.... }/>
На login/logout можно и страницу reload-ить на всякий случай.
А случаи бывают разные: https://en.wikipedia.org/wiki/Session_fixation
Надо понимать, что основная проверка прав на что-то все равно должна быть на сервере, т. к. с клиента можно, при желании, послать любые запросы.
content={ grants => в аргумент callback, чтоб не рендерить то, что не будем показывать.