Административный веб интерфейс для Личного Кабинета Машиниста
Главный стек: React, Redux (Saga), styled-components
- UI. Для простых элементов лучше писать свой UI-компонент или использовать уже существующий из а-ля UI-кита на проекте:
./components/ui/*
. Пример: Spinner, Button, Modal. Для более сложных задач можно использовать готовые решения, напримерreact-select
илиreact-day-picker
. В противном случае писать в UI-ките обертку над ними, как сделало с Modal. - Типизация. Тут нет TypeScript, так что
prop-types
твой лучший друг в хоть какой-то типизации компонентов. - Стиль. Конечно же используй
eslint
иprettier
. На пре-коммите проверяется все husky. - Функциональщина. Предпочтительно писать функциональные компоненты, дробя большие тяжелые классы. Так же лучше использовать
useSelector
иuseDispatch
вместоconnect
. Пример самостоятельного, но очень простого компонента:./components/LibraryForm/Comments/index.js
- Стор. Так как 95% ситуаций при работе со стором связаны с обработкой данных с сервера, то почти все сущности стора основаны на
redux-saga-routines
. Бойлерплейт никуда не уходит, но его становится меньше и появляется систематизация работы с запросами и структурированность между собой. Более подробно в конце readme.
Иногда можно делать запросы напрямую в компоненте, если эта логика используется только один раз в этом месте и больше нигде. - ?. Пока нет возможности добавить optional-chaining в проект. Так && что && да.
- Константы. Любые числа, константы лучше выносить в
./constants/common
- Нейминг. Это очень важно. Очевидно никаких a, b, c, d. Вспомогательные utils функции лучше называть действием, что они возвращают, например
getCurrentTime
, но хендлеры -- местом, где они исполняются, напримерhandleClickSubmitButton
вместоsendDocument
.
В сторе все попроще: чтобы не было непонятной мешанины, когда ты в компоненте не понимаешь, где селектор, а где стейт; где экшен, а где функция. Лучше давать такие имена: селекторам -..Seleсtor
, рутинам -..Routine
, сагам -on..
,..Watcher
.
Пример: "postsSelector", "fetchPostsRoutine", onFetchPosts", "fetchPostsWatcher". Тогда стейт и функция в компоненте будут соответственно "posts" и "fetchPosts". - Комментарии. Это хорошо, когда много всего и ничего непонятно. Отдельно неплохо документировать часто-используемые UI-компоненты, которые могут реагировать на over9000 пропсов. Такие заметки очень помогают быстро понять, что и как работает. Но в идеале код должен быть самодокументированным.
- Склонируй репозиторий
- Переключись на ветку
test
- Установи зависимости
- Добавь новый
.env.development.local
файл в корень проекта с переменной окружения:REACT_APP_LKM_API=https://lkm.rzhd.ml
- Запусти проект:
npm run start-dev
- Работай только на Chrome без CORS
Ниже как сделать последний шаг
- Создай ярлык главного исполняемого файла
chrome.exe
. - Открой свойства ярлыка.
- После пути (кавычек) до исполняемого файла добавь флаги для отключения безопасности.
Пример:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --disable-gpu --user-data-dir=~/chromeTemp
- Быстрый, но не комфортный способ для ежедневной работы. Просто открой терминал и введи:
open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir=/tmp/chrome_dev_test --disable-web-security
. - Конечно еще можно сделать Automator скрипт.
- Рекомендованный вариант (VS Code):
- Установи расширение "Debugger for Chrome"
- В меню дебага добавь новый конфиг для Chrome
Он должен выглядить так:
{ "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", "url": "http://localhost:3000", "webRoot": "${workspaceFolder}", "userDataDir": "/tmp/chrome_dev_test", "runtimeArgs": ["--disable-web-security"], "sourceMaps": true }
-
~/src/api
- обертки для API-запросов c помощиью axios, разделенные по сущностям/роутам. Если надо интегрировать новые API-методы, то тут в зависимости от функциональной сущности в нужном файле добавляешь методы. Они потом будут использованы в сагах и компонентах -
~/src/store
- главная папочка Redux, где так же по функциональным/роутовым сущностям разбиты глобальные стейты -
~/src/store/example
./routines.js
- создаешь по одной рутине на один API-запрос, напримерfetchExampleRoutine
./sagas.js
- импортируешь нужный api-объект, создаешь (try, catch) 1 сагу на 1 запрос, напримерonFetchExample
, где обрабатыаешь (put) все шаги рутины (request, success, failure), включая обращение (call) к api. Потом вешаешь (takeLatest) на все это сагу-наблюдателя, напримерfetchExampleWatcher
, который добавляешь в массив главного экспорта../reducers.js
- все как обычно, но мы импортируем рутины, а не типы экшенов и в сагах контролируем, в какой шаг рутины, что будет (и будет ли вообще) вaction.payload
. Тут обрабатываешь все значимые шаги рутины, напримерfetchExampleRoutine.SUCCESS
, чтобы изменить глобальный стейт в сторе.