когда нечего делать, а творческая душа требует реализации и хочется что-то сделать или написать, то я пишу сюда или делаю что-то на этом сайте. Кому интересна web-разработка, wordpress и то что рядом с этим, то заходите на мой сайт и читайте всякое...
Приватный роут в react-router-dom. Пример использования react-redux
Йо-йо! Недавно (июнь 2019) доделывал сайт для бонусной системы одной сети пиццерий в своём городе. Для хранения данных я использовал redux. Авторизация или регистрация использовали один из action creator’ов и так мои компоненты могли понять, что пользователь зарегистрирован или авторизирован на сайте.
Приватный route
Это такой глупый компонент в который мы передаём true или false, и он либо рендерит какой-то компонент, либо делает redirect.
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import React, {Component, Suspense, lazy } from 'react';
import PrivateRoute from './routs/PrivateRoute';
import './css/App.css';
import logo from './img/logo.png';
import PageMain from './pages/Main/PageMain';
const PageRegister = lazy(() => import('./components/Registration/RegistrationContainer'));
const PageAuth = lazy(()=>import('./components/Auth/AuthContainer'));
const PageLk = lazy(()=> import('./pages/Lk/Page__Lk'));
const auth = // некая переменная или функция которая возвращает значение true или false в зависимости авторизирован пользователь или нет
class App extends Component{
render(){
return (
<div className="container">
<div className="row">
<Router>
<div className="col-12 header">
<div className="row">
<div className="col-md-6">
<Link to="/" className="text-white">
<img title="На главную" className="img-fluid" src={logo} alt="logtype"/>
</Link>
</div>
<div className="col-md-6">
<p className="text-white header__phone">Какой-то текст</p>
</div>
</div>
</div>
<Suspense fallback={<div className="preloader">Загрузка...</div>}>
<Switch>
<Route exact path="/" component={ (()=>(<PageMain />)) } />
<Route path="/register" component={ ()=>(<PageRegister/>) } />
<Route path="/auth" component={ ()=>(<PageAuth/>) } />
<PrivateRoute auth={auth} path="/lk" component={ ()=>(<PageLk/>) } />
</Switch>
</Suspense>
</Router>
</div>
</div>
);
}
}
export default App;
Если вы хотите подробнее познакомиться c router то прочитайте статью react-router-dom.
Redux и react-router-dom
Теперь нам нужно понимать авторизирован пользователь или нет. Для этого я использую redux. Я создал папку store в корне проекта и в нём папку auth. В папке два файла actions.js и redusers.js
В файле actions.js я создал несколько action creater’ов
Если вам сложно разобраться с redux рекомендую посмотреть курс на youtube от codedojo.
Создаём store
Переходим в компонент с роутером и модифицируем его
// Импортируем redux и наши redusers
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import rootRedusers from './store/redusers'
Создаём store
const store = createStore(rootRedusers);
Оборачиваем весь наш компонент в <Provider>
return(
<Provider store={store}>
// Остальной код компонента
</Provider>
)
Тут через store.getState() мы проверяем есть ли на данный момент ‘auth’ в storе. В начале жизни нашего приложения его может не быть. И ещё мы проверяем наше isAuthValue на true
Как менять isAuthValue
У меня есть AuthContainer, который лежит по адресу — /components/Auth/AuthContainer’. и там же лежит компонент Auth в котором и происходит сама регистрация, лежит вёрстка и т.д.
Создание контейнера
AuthContainer — умный компонент, который и передаёт данные в Auth. У меня получился вот такой код компонента:
import React, { Component } from 'react';
import Auth from './Auth';
// Нужно, чтобы передать наш store и методы в AuthContainer
import { connect } from 'react-redux';
// Импортирую экшены, которые буду использовать в своём приложении
import {
setPhoneText,
setPasswordText,
setValidPassword,
setValidPhone,
setIsAuthValue
} from '../../store/auth/actions';
class AuthContainer extends Component {
render() {
// Передаю props'ы в Auth
return <Auth
phone={this.props.phone}
password={this.props.password}
isValidPhone={this.props.isValidPhone}
isValidPassword={this.props.isValidPassword}
isAuthValue={this.props.isAuthValue}
setPhoneText={this.props.setPhoneText}
setPasswordText={this.props.setPasswordText}
setValidPhone={this.props.setValidPhone}
setValidPassword={this.props.setValidPassword}
setIsAuthValue={this.props.setIsAuthValue}
/>
}
}
// Перечисляю, что из состояний store будет передано компоненту AuthContaine и далее Auth
const mapStateToProps = state => {
return {
phone: state.auth.phone,
password: state.auth.password,
isValidPhone: state.auth.isValidPhone,
isValidPassword: state.auth.isValidPassword,
isAuthValue: state.auth.isAuthValue
};
};
// Перечисляю методы которые будут переданы в AuthConatainer, а потом в Auth
const mapDispatchToProps = {
setPhoneText,
setPasswordText,
setValidPassword,
setValidPhone,
setIsAuthValue
}
// Через функцию connect передаю всё в компонент AuthContainer
export default connect(mapStateToProps, mapDispatchToProps)(AuthContainer);
Обратите внимание, что в итоге компонет AuthConatainer будет использоваться внутри <Provider> иначе ничего не сработает.
Использование reduser’а
После того как мы передали в Auth reduser’ы из AuthContainer у нас появилась функция this.props.setIsAuthValue(bool).
В тот момент, когда мы убедились, что пользователь авторизировался мы можем вызвать this.props.setIsAuthValue(true), таким образом значение isAuthValue измениться на true. Кстати если вы делаете кросс-доменные запросы для авторизации как я, то вам может быть полезной статья «fetch и cors, пример на reactjs«
Для лучшего UX после авторизации я перенаправлял пользователей в личный кабинет. Для этого мне понадобилось изменить state компонента, чтобы вызвать повторный reder, проверить значение isAuthValue. Примерно это может быть вот так:
На самом деле, если разобраться, это всё довольно не сложно. При частой практике вы будете очень быстро справляться с react-redux и react-dom-router будет помогать делать шустрые SPA и не станет усложнением. Однажды я расскажу как настроить виртуальный сервер windows и apache так, чтобы работал router как нужно.
Про комментарии
Праведный «срач» поддерживается, а также вопросы и собственный опыт.
Поддержи Xakplant
Я давно хочу развить видеоверсию, но пока этого не получается из-за нехватки ресурсов. Сейчас я собираю деньги на новый компьютер и микрофон. Поддержи xaklant и ты увидишь полезные видео быстрее.