Роутинг
Стероиды позволяют задать единое дерево роутов всего проекта, которое можно считать картой сайта.
В проекте, как правило, дерево задается в файле routes/index.ts, где корневым роутом root является главная
страница (как правило, с адресом /), а ветви дерева задаются через items. Каждая страница описывается
объектом с интерфейсом IRouteItem.
Задав такое дерево, вы получаете сразу несколько преимуществ:
- Можно создавать ссылки по ID роута:
<Link toRoute='root'>...</Link>'. - Можно выбрать ветвь дерева роутов и отрендерить по нему навигацию:
<Nav items='profile'/>. - Лейблы ссылок и заголовки страниц будут браться из описанного дерева роутов.
- Относительный путь до страниц –
url, описывается только в дереве роутов, его легко изменять без рефакторинга проекта. - Разработчик может наглядно увидеть всю карту проекта, просто открыв дерево роутов.
- У роутов можно указывать роли –
roles, для ограничения доступа к странице по ролям пользователей.
Пример дерера роутов из трех страниц - главной и страниц профиля:
import IndexPage from './IndexPage';
import ProfileGeneral from './ProfileGeneral';
import ProfileSettings from './ProfileSettings';
import {IRouteItem} from '@steroidsjs/core/ui/nav/Router/Router';
export const ROUTE_ROOT = 'root';
export const ROUTE_PROFILE = 'profile';
export const ROUTE_PROFILE_GENERAL = 'profile_general';
export const ROUTE_PROFILE_SETTINGS = 'profile_settings';
export default {
id: ROUTE_ROOT,
exact: true,
path: '/',
label: __('Главная страница'),
component: IndexPage,
roles: [null, 'user'], // могут видеть гости и авторизованные пользователи
items: {
[ROUTE_PROFILE]: {
label: __('Профиль'),
path: '/profile',
redirectTo: true,
roles: ['user'], // могут видеть только авторизованные пользователи
items: {
[ROUTE_PROFILE_GENERAL]: {
label: __('Основная информация'),
path: '/general', // указываем только часть пути, остальное добавится от родителя
component: ProfileGeneral,
// тут роли не указываем, они наследуются от родителя
},
[ROUTE_PROFILE_SETTINGS]: {
label: __('Настройки'),
path: '/settings',
component: ProfileSettings,
},
},
},
},
} as IRouteItem;Относительные и абсолютные пути
По умолчанию, для вложенных роутов нужно указывать только сегмент пути, полный путь автоматически сформируется с добавлением части родительского пути.
Например:
// src/routes/index.ts
import {IRouteItem} from '@steroidsjs/core/ui/nav/Router/Router';
import IndexPage from './IndexPage';
import LoginPage from './LoginPage';
import SignUpPage from './SignUpPage';
export const ROUTE_ROOT = 'root';
const roles = [null];
export default {
id: ROUTE_ROOT,
exact: true,
path: '/',
component: IndexPage,
roles,
items: {
auth: {
exact: true,
path: '/auth',
roles,
items: {
login: {
exact: true,
path: '/login',
roles,
component: LoginPage,
}, // LoginPage будет доступен по URL /auth/login
signUp: {
exact: true,
path: '/sign-up',
roles,
component: SignUpPage
} // SignUpPage будет доступен по URL /auth/sign-up
}
}
}
} as IRouteItem;Чтобы использовать дерево роутов с указанием абсолютных путей, нужно добавить в файле Application.tsx флаг alwaysAppendParentRoutePath для routerProps:
// src/Application.tsx
import useApplication from '@steroidsjs/core/hooks/useApplication';
export default function Application() {
const {renderApplication} = useApplication({
routerProps: {
alwaysAppendParentRoutePath: false, // укажем флаг для использования абсолютных путей
},
/* ... */
});
return renderApplication();
}Тогда, для доступа к страницам авторизации и регистрации по тем же URL, что и в предыдущем примере будет необходимо исправить структуру дерева роутов на:
// src/routes/index.ts
import {IRouteItem} from '@steroidsjs/core/ui/nav/Router/Router';
import IndexPage from './IndexPage';
import LoginPage from './LoginPage';
import SignUpPage from './SignUpPage';
export const ROUTE_ROOT = 'root';
const roles = [null];
export default {
id: ROUTE_ROOT,
exact: true,
path: '/',
component: IndexPage,
roles,
items: {
auth: {
exact: true,
path: '/auth',
roles,
items: {
login: {
exact: true,
path: '/auth/login', // Указываем абсолютный путь
roles,
component: LoginPage,
}, // LoginPage будет доступен по URL /auth/login
signUp: {
exact: true,
path: '/auth/sign-up', // Указываем абсолютный путь
roles,
component: SignUpPage
} // SignUpPage будет доступен по URL /auth/sign-up
}
}
}
} as IRouteItem;Настройки роута
Параметры path, exact - передаются напрямую в React Router. Их описание можно посмотреть в официальной документации React Router.
Название и лейбл
Для каждого роута можно указать label и title. Приложение само может распоряжаться по какой логике использовать
один или другой, но изначально смысл заложен такой - label используется для названия ссылок, а title - для заголовка
страниц (а если не задан - используется label).
Отображение ссылок в дереве навигации
Бывают ситуации, когда не нужно отображать ссылку или кнопку в навигации для перехода на роут. Например, если нужно добавить роут для настроек профиля, но не добавлять его в навигацию.
Для таких случаев удобно использовать параметр isNavVisible, в значении false.
Модифицируем дерево роутов так, чтобы путь /settings не был виден в навигации:
/* ... */
export default {
id: ROUTE_ROOT,
exact: true,
path: '/',
label: __('Главная страница'),
component: IndexPage,
roles: [null, 'user'],
items: {
[ROUTE_PROFILE]: {
/* ... */
items: {
/* ... */
[ROUTE_PROFILE_SETTINGS]: {
label: __('Настройки'),
path: '/settings',
component: ProfileSettings,
isNavVisible: false, // скроем роут из навигации
},
},
},
},
} as IRouteItem;Редирект
Для автоматического редиректа роута на страницу, необходимо задать свойство redirectTo, в котором указывается path до страницы.
Например:
// src/routes/index.ts
import {IRouteItem} from '@steroidsjs/core/ui/nav/Router/Router';
import IndexPage from './IndexPage';
import LoginPage from './LoginPage';
import SignUpPage from './SignUpPage';
export const ROUTE_ROOT = 'root';
const roles = [null];
export default {
id: ROUTE_ROOT,
exact: true,
path: '/',
component: IndexPage,
roles,
items: {
auth: {
exact: true,
path: '/auth',
roles,
redirectTo: '/auth/login', // Указываем ссылку, на которую пользователь автоматически будет перенаправлен при попытке доступа к /auth
items: {
login: {
exact: true,
path: '/login',
roles,
component: LoginPage,
},
signUp: {
exact: true,
path: '/sign-up',
roles,
component: SignUpPage
}
}
}
}
} as IRouteItem;Часто бывает, что необходимо сделать редирект на дочернюю страницу раздела. Например, как в предыдущем примере, чтобы /auth перенаправлял на
/auth/login, где login - одна из дочерних страниц ветви auth. В таком случае можно задать redirectTo в true,
чтобы редирект был сделан на первую дочернюю страницу.
// src/routes/index.ts
import {IRouteItem} from '@steroidsjs/core/ui/nav/Router/Router';
import IndexPage from './IndexPage';
import LoginPage from './LoginPage';
import SignUpPage from './SignUpPage';
export const ROUTE_ROOT = 'root';
const roles = [null];
export default {
id: ROUTE_ROOT,
exact: true,
path: '/',
component: IndexPage,
roles,
items: {
auth: {
exact: true,
path: '/auth',
roles,
redirectTo: true, // Обратите внимание, не обязательно указывать ссылку, если необходимо перенаправить на первый роут из items
items: {
login: {
exact: true,
path: '/login',
roles,
component: LoginPage,
},
signUp: {
exact: true,
path: '/sign-up',
roles,
component: SignUpPage
}
}
}
}
} as IRouteItem;