Skip to content

Instantly share code, notes, and snippets.

@lomeat
Created June 18, 2021 15:12
Show Gist options
  • Save lomeat/658b2daacf9eae647f492a47896cff54 to your computer and use it in GitHub Desktop.
Save lomeat/658b2daacf9eae647f492a47896cff54 to your computer and use it in GitHub Desktop.

Admin UI

Описание

Административный веб интерфейс для Личного Кабинета Машиниста

Главный стек: 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 пропсов. Такие заметки очень помогают быстро понять, что и как работает. Но в идеале код должен быть самодокументированным.

Установка & Запуск

  1. Склонируй репозиторий
  2. Переключись на ветку test
  3. Установи зависимости
  4. Добавь новый .env.development.local файл в корень проекта с переменной окружения: REACT_APP_LKM_API=https://lkm.rzhd.ml
  5. Запусти проект: npm run start-dev
  6. Работай только на Chrome без CORS

Ниже как сделать последний шаг

Windows

  1. Создай ярлык главного исполняемого файла chrome.exe.
  2. Открой свойства ярлыка.
  3. После пути (кавычек) до исполняемого файла добавь флаги для отключения безопасности.

Пример:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --disable-gpu --user-data-dir=~/chromeTemp

Mac OS X

  • Быстрый, но не комфортный способ для ежедневной работы. Просто открой терминал и введи: 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):
    1. Установи расширение "Debugger for Chrome"
    2. В меню дебага добавь новый конфиг для 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
    }
    

Пару слов о работе с API и Redux store

  • ~/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, чтобы изменить глобальный стейт в сторе.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment