Магазин на JavaScript, часть 10 из 19. Маршруты, панель навигации, контекст приложения
16.12.2021
Теги: Backend • Express.js • Frontend • JavaScript • Node.js • ORM • React.js • Web-разработка • БазаДанных • ИнтернетМагазин • КаталогТоваров • Корзина • Фреймворк
Маршруты приложения
В React имеется своя система маршрутизации, которая позволяет сопоставлять запросы к приложению с определенными компонентами. Ключевым звеном в работе маршрутизации является модуль react-router, который состоит из react-router-dom и react-router-native. Для браузерных приложений предназначен модуль react-router-dom, который мы уже установили. Добавляем маршруты приложения в файл App.js
:
import { BrowserRouter, Routes, Route } from 'react-router-dom' import Shop from './pages/Shop.js' import Product from './pages/Product.js' import Basket from './pages/Basket.js' import Login from './pages/Login.js' import Signup from './pages/Signup.js' import Delivery from './pages/Delivery.js' import Contacts from './pages/Contacts.js' import NotFound from './pages/NotFound.js' const App = () => { return ( <BrowserRouter> <Routes> <Route path="/" element={<Shop />} /> <Route path="/product/:id" element={<Product />} /> <Route path="/basket" element={<Basket />} /> <Route path="/login" element={<Login />} /> <Route path="/signup" element={<Signup />} /> <Route path="/delivery" element={<Delivery />} /> <Route path="/contacts" element={<Contacts />} /> <Route path="*" element={<NotFound />} /> </Routes> </BrowserRouter> ) } export default App
Но здесь далеко не все маршруты. Давайте прикинем, какие вообще маршруты могут быть. Во-первых, public-маршруты, которые доступны всем посетителям. Во-вторых, auth-маршруты, которые доступны только авторизованным пользователям. В-третьих, admin-маршруты, которые доступны только администратору магазина. Давайте все маршруты определим в компоненте components/AppRouter.js
.
import { Routes, Route } from 'react-router-dom' import Shop from '../pages/Shop.js' import Login from '../pages/Login.js' import Signup from '../pages/Signup.js' import Delivery from '../pages/Delivery.js' import Contacts from '../pages/Contacts.js' import NotFound from '../pages/NotFound.js' import User from '../pages/User.js' import Admin from '../pages/Admin.js' const publicRoutes = [ {path: '/', Component: Shop}, {path: '/login', Component: Login}, {path: '/signup', Component: Signup}, {path: '/delivery', Component: Delivery}, {path: '/contacts', Component: Contacts}, {path: '*', Component: NotFound}, ] const authRoutes = [ {path: '/user', Component: User}, ] const adminRoutes = [ {path: '/admin', Component: Admin}, ] const AppRouter = () => { const isAuth = true const isAdmin = true return ( <Routes> {publicRoutes.map(({path, Component}) => <Route key={path} path={path} element={<Component />} /> )} {isAuth && authRoutes.map(({path, Component}) => <Route key={path} path={path} element={<Component />} /> )} {isAdmin && adminRoutes.map(({path, Component}) => <Route key={path} path={path} element={<Component />} /> )} </Routes> ) } export default AppRouter
Теперь компонент App.js
будет просто импортировать AppRouter.js
:
import { BrowserRouter } from 'react-router-dom' import AppRouter from './components/AppRouter.js' const App = () => { return ( <BrowserRouter> <AppRouter /> </BrowserRouter> ) } export default App
Панель навигации
Создаем новый компонент NavBar.js
в директории conponents
:
import { Container, Navbar, Nav } from 'react-bootstrap' const NavBar = () => { const isAuth = true const isAdmin = true return ( <Navbar bg="dark" variant="dark"> <Container> <Navbar.Brand href="/">Магазин</Navbar.Brand> <Nav className="mr-auto"> <Nav.Link href="/delivery">Доставка</Nav.Link> <Nav.Link href="/contacts">Контакты</Nav.Link> {isAuth ? ( <Nav.Link to="/user">Личный кабинет</Nav.Link> ) : ( <> <Nav.Link to="/login">Войти</NavLink> <Nav.Link to="/signup">Регистрация</Nav.Link> </> )} {isAdmin && ( <Nav.Link href="/admin">Панель управления</Nav.Link> )} </Nav> </Container> </Navbar> ); }; export default NavBar
Тут возникает трудность — как подружить компоненты react-bootstrap
с компонентами react-router-dom
? Сейчас у нас обычные ссылки, а нам нужны ссылки из react-router-dom
— то есть <Link to="…">
и <NavLink to="…">
, которые не будут загружать с сервера страницы целиком, а только изменять состояние приложения.
Нужно заменить <Nav.Link href="…">
на <NavLink to="…">
и добавить еще className
, который можно посмотреть в панели разработчика браузера. Так что в итоге получился такой код компонента:
import { Container, Navbar, Nav } from 'react-bootstrap' import { NavLink } from 'react-router-dom' const NavBar = () => { const isAuth = true const isAdmin = true return ( <Navbar bg="dark" variant="dark"> <Container> <NavLink to="/" className="navbar-brand">Магазин</NavLink> <Nav className="ml-auto"> <NavLink to="/delivery" className="nav-link">Доставка</NavLink> <NavLink to="/contacts" className="nav-link">Контакты</NavLink> {isAuth ? ( <NavLink to="/user" className="nav-link">Личный кабинет</NavLink> ) : ( <> <NavLink to="/login" className="nav-link">Войти</NavLink> <NavLink to="/signup" className="nav-link">Регистрация</NavLink> </> )} {isAdmin && ( <NavLink to="/admin" className="nav-link">Панель управления</NavLink> )} </Nav> </Container> </Navbar> ) } export default NavBar
Контекст приложения
Создаем новый компонент AppContext.js
в директории conponents
:
import React from 'react' const AppContext = React.createContext() // контекст, который будем передавать const context = { user: { email: 'ivanov@mail.ru', isAuth: true, isAdmin: false, } } const AppContextProvider = (props) => { return ( <AppContext.Provider value={context}> {props.children} </AppContext.Provider> ); } export {AppContext, AppContextProvider}
Обернем все наше приложение в AppContextProvider
, чтобы в любом месте иметь доступ к контексту через хук useContext
.
import React from 'react' import ReactDOM from 'react-dom' import App from './App' import { AppContextProvider } from './components/AppContext.js'; ReactDOM.render( <React.StrictMode> <AppContextProvider> <App /> </AppContextProvider> </React.StrictMode>, document.getElementById('root') );
Теперь в компонентах AppRouter
и NavBar
вместо констант isAuth
и isAdmin
будем использовать данные из контекста.
/* .......... */ import { AppContext } from './AppContext.js' import { useContext } from 'react' /* .......... */ const AppRouter = () => { const { user } = useContext(AppContext) return ( <Routes> {publicRoutes.map(({path, Component}) => <Route key={path} path={path} element={<Component />} /> )} {user.isAuth && authRoutes.map(({path, Component}) => <Route key={path} path={path} element={<Component />} /> )} {user.isAdmin && adminRoutes.map(({path, Component}) => <Route key={path} path={path} element={<Component />} /> )} </Routes> ) } export default AppRouter
/* .......... */ import { AppContext } from './AppContext.js' import { useContext } from 'react' const NavBar = () => { const { user } = useContext(AppContext) return ( <Navbar bg="dark" variant="dark"> <Container> <NavLink to="/" className="navbar-brand">Магазин</NavLink> <Nav className="ml-auto"> <NavLink to="/delivery" className="nav-link">Доставка</Nav.Link> <NavLink to="/contacts" className="nav-link">Контакты</Nav.Link> {user.isAuth ? (.....) : (.....)} {user.isAdmin && (.....)} </Nav> </Container> </Navbar> ) } export default NavBar
- Магазин на JavaScript, часть 19 из 19. Редактирование характеристик и рефакторинг приложения
- Магазин на JavaScript, часть 18 из 19. Панель управления: редактирование категорий и брендов
- Магазин на JavaScript, часть 17 из 19. Панель управления: список заказов, категорий и брендов
- Магазин на JavaScript, часть 15 из 19. Работа с заказами на сервере, оформление заказа
- Магазин на JavaScript, часть 14 из 19. Кнопка «Назад», страница товара, корзина покупателя
- Магазин на JavaScript, часть 13 из 19. Хранилище каталога, компонент витрины, кнопка «Назад»
- Магазин на JavaScript, часть12 из 19. Запросы на сервер, состояние приложения, Signup и Login
Поиск: Backend • Express.js • Frontend • JavaScript • Node.js • ORM • React.js • Web-разработка • База данных • Интернет магазин • Каталог товаров • Корзина • Фреймворк