Skip to content

Latest commit

 

History

History
362 lines (295 loc) · 17.4 KB

10. Реакт — не фреймворк, но как построить проект?.md

File metadata and controls

362 lines (295 loc) · 17.4 KB

Реакт — не фреймворк, но как построить проект?

Архитектура и основные модули из экосистемы Реакта

Чем в сознании разработчика библиотека отличается от фреймворка? Библиотека решает конкретную задачу, фреймворк даёт экосистему и диктует архитектуру.

Когда впервые знакомишься с Реактом, то после всяких Ангуларов не понимаешь, как же с ним работать: это же библиотека для вёрстки, почему я должен её использовать? У меня всё хорошо, есть @angular/common/http, @angular/universal, @angular/router и прочее, а тут мне нужно из говна и палок слепить проект, не хочу этим заниматься!

Так-то оно правда, но вы пользуетесь Реактом в 2018 году, а не в 2014, когда ещё ничего не было, так что сегодня мы рассмотрим основные библиотеки, которые можно использовать с Реактом.

Библиотеки

Стилизация

Как вы понимаете, Styled Components. Эту идеальную библиотеку пока никто не переплюнет.

Роутинг

Его мы тоже проходили, это Реакт-роутер.

ХТТП-запросы

Сравнительно новый браузерный АПИ для запросов.

Если нужна поддержка старых браузеров, используют полифилл github/fetch.

(полифилл это библиотека, которая предоставляет новую функциональность через старые технологии — например, в этом случае fetch работает на XMLHttpRequest)

Формы

В интерфейсах часто бывают формы: инпуты, селекты и прочие поля ввода, а у форм ведь должна быть валидация данных и прочие возможности.

Formik либо react-final-form.

Хранение данных

Стейт компонента. Да, я не шучу, в 99.99999999% случаев используйте локальный стейт компонента или его родителей.

Почему часто советуют Редакс или Мобкс? Потому что в 2015 Редакс был очень модным и все старались его воткнуть себе в проект, а потом оказалось, что он на пустом месте усложняет проект. Сам Даня Абрамов говорит, что скорее всего вам не нужен Редакс.

Модальные окна

Либо react-portal, либо ReactDOM.createPortal().

Бутстрап или его замена

Часто советуют Ant Design, но лично я не пользовался: у меня всегда был свой дизайн.

Работа с <head />

Тайтлы, описания, опенграф-теги обновляются через react-helmet.

Даты

date-fns и react-day-picker.

moment.js слишком жирный и придерживается мутабельности — это неудобно.

Селекты и автодополнения

Раньше был react-select, но он вообще не поддерживается автором.

Сейчас есть downshift, но это достаточно низкоуровневая библиотека, поверх которой можно строить свои компоненты — посмотрите примеры в документации.

Карты

Зависит от сервиса, который вы используете: например, google-map-react или react-yandex-maps.

Графики

Обычно все графики работают поверх d3.js — это самая мощная библиотека для работы с ними, посмотрите на эти демки, которые собирает автор.

vx — библиотека, которая дружит d3 и Реакт.


Обычно хватает поиска в Гугле «react x», а после остаётся только выбрать.

Вот несколько правил:

  • версия желательно не должна быть 0.х: по Семверу всё может сломаться,
  • понятные описания релизов: если нет файла CHANGELOG.md или вкладка Releases на Гитхабе пустует, то вам сложно будет обновляться,
  • должны быть ишью и пулл-реквесты: библиотекой должен пользоваться кто-то кроме её автора.

А как же Вебпак и Бейбель

У вас есть CRA, который скрыл настройку Вебпака и Бейбеля под собой. Можете выдохнуть.

Архитектура проекта

Едем дальше. Частый вопрос: а как организовывать проект?

Бизнес-логика превыше всего

Организация проекта строится по бизнес-логике: нет нужды делать кучу директорий src/components/Properties, src/containers/Properties, src/actions/Properties, src/api/Properties, если можно всё положить в src/Properties/{actions,api}.

Объединять по доменам проще, чем бегать по 10 директориям, вы же в один момент времени работаете только с одной сущностью?

Например, вам нужно сделать авторизацию, Auth: две страницы (логин, регистрация), несколько компонентов, запросы к серверу. Когда вы её делаете, вы же не отвлекаетесь на другие компоненты или файлы? Вы работаете конкретно над авторизацией.

Думайте продуктом, а не ненужными абстракциями типа компонентов или контейнеров. Люди в вашем продукте пользуются конкретной функциональностью, а не экшенами, редьюсерами или контейнерами.

Избавьтесь от components

Нет, я серьёзно: даже после предыдущего пункта люди часто оставляют директорию components. У вас всё приложение построено на компонентах, зачем директорию отдельно создавать?

Если хотите какой-нибудь хедер или футер переиспользовать на разных страницах, то положите в корень src, а не в src/components или src/shared.

Для интерфейсных вещей типа форм, кнопок и прочего обычно используют src/ui.

Не создавайте директории ради одного файла

Часто вижу src/Header, в котором лежит сиротливый index.js. Зачем? На будущее? Преждевременные оптимизации — корень всех бед.

Положите в src/Header.js.

Смешивать стили, рендер и логику можно

Это же компонентный подход, ничего страшного если в одном файле будут СК, "главный" Реакт-компонент с запросами или обработчиками событий.

Если стилей много, то ваш выбор styled.js с экспортами рядом с файлом.

Переиспользуйте компоненты

Ещё один частый вопрос: а как мелко дробить компоненты?

Дробите до переиспользуемости. Если у вас есть два огромных блока, в которых повторяется только кнопка, то вынесите кнопку в отдельный компонент, а всё остальное оставьте как есть: смысл дробить меньше?

Но если работать неудобно с компонентом — то дробите тоже.

Итог

Сегодняшним уроком я хотел вам показать, что Реакт это устоявшаяся экосистема, где либо используются стандарты (фетч), либо есть давно устоявшиеся библиотеки, заточенные чисто под Реакт.


Пример неплохой архитектуры? Например, моя неплоха, хоть и неидеальна.

src
├── About.js
├── Announces
│   ├── CourseReactAnnounce.js
│   └── index.js
├── App.js
├── Buy
│   ├── Closed.js
│   ├── Medium.svg
│   ├── Old.js
│   ├── Telegram.svg
│   ├── VK.svg
│   ├── YouTube.svg
│   ├── index.js
│   └── tinkoff.js
├── Companies
│   ├── everpoint.js
│   └── index.js
├── Courses
│   ├── Lessons
│   │   ├── Header.js
│   │   ├── Lesson.js
│   │   ├── ReactMarkdown.js
│   │   ├── Stage.js
│   │   ├── external-link.svg
│   │   └── styled.js
│   ├── React
│   │   ├── About.js
│   │   ├── Antihire.js
│   │   ├── Buy.js
│   │   ├── Changes
│   │   │   ├── clocks.svg
│   │   │   └── index.js
│   │   ├── Footer
│   │   │   ├── index.js
│   │   │   ├── md.svg
│   │   │   ├── tg.svg
│   │   │   ├── vk.svg
│   │   │   └── yt.svg
│   │   ├── Header
│   │   │   ├── atom.png
│   │   │   └── index.js
│   │   ├── History
│   │   │   ├── index.js
│   │   │   └── max.svg
│   │   ├── Kursach
│   │   │   ├── index.js
│   │   │   └── kursach.svg
│   │   ├── LandingUI.js
│   │   ├── Project
│   │   │   ├── Aviasales
│   │   │   │   ├── aviasales.svg
│   │   │   │   └── index.js
│   │   │   ├── Dates.js
│   │   │   ├── Format
│   │   │   │   ├── format.svg
│   │   │   │   ├── assistant.svg
│   │   │   │   ├── code_review.svg
│   │   │   │   └── index.js
│   │   │   └── index.js
│   │   ├── Quote.js
│   │   ├── Reviews
│   │   │   ├── Review.js
│   │   │   └── index.js
│   │   ├── SoftSkills
│   │   │   ├── index.js
│   │   │   ├── softskills_0.jpg
│   │   │   ├── softskills_0_mobile.png
│   │   │   ├── softskills_1.jpg
│   │   │   ├── softskills_1_mobile.png
│   │   │   ├── softskills_2.jpg
│   │   │   ├── softskills_2_mobile.png
│   │   │   ├── softskills_small_0.jpg
│   │   │   ├── softskills_small_0_mobile.png
│   │   │   ├── softskills_small_1.jpg
│   │   │   ├── softskills_small_1_mobile.png
│   │   │   ├── softskills_small_2.jpg
│   │   │   └── softskills_small_2_mobile.png
│   │   └── index.js
│   ├── Verstka
│   │   ├── Landing
│   │   │   ├── About.js
│   │   │   ├── Buy.js
│   │   │   ├── Chat.js
│   │   │   ├── Course.js
│   │   │   ├── Feedback
│   │   │   │   ├── bot.png
│   │   │   │   ├── chats.png
│   │   │   │   ├── code-review-feedback.png
│   │   │   │   └── index.js
│   │   │   ├── Format
│   │   │   │   ├── index.js
│   │   │   │   └── [email protected]
│   │   │   ├── Kursach
│   │   │   │   ├── [email protected]
│   │   │   │   └── index.js
│   │   │   ├── Questions
│   │   │   │   ├── Question.js
│   │   │   │   ├── data.js
│   │   │   │   └── index.js
│   │   │   ├── Reviews
│   │   │   │   ├── index.js
│   │   │   │   └── [email protected]
│   │   │   └── index.js
│   │   ├── Study
│   │   │   ├── Footer.js
│   │   │   ├── link.svg
│   │   │   ├── Lessons.js
│   │   │   ├── codeRenderer.js
│   │   │   └── styles.js
│   │   └── index.js
│   └── index.js
├── Footer
│   ├── index.js
│   ├── md.svg
│   ├── tg.svg
│   ├── vk.svg
│   └── yt.svg
├── Frontend
│   ├── About.js
│   ├── Buy.js
│   ├── Feedback
│   │   ├── [email protected]
│   │   └── index.js
│   ├── Format.js
│   ├── Kursach
│   │   ├── index.js
│   │   └── screenshot.png
│   ├── Landing.js
│   ├── LandingFeb
│   │   ├── Program.js
│   │   ├── Steps.js
│   │   ├── aviasales.png
│   │   └── index.js
│   ├── NewYearBuy.js
│   ├── Payed.js
│   ├── Plan.js
│   ├── Premium.js
│   ├── Program.js
│   ├── Questions
│   │   ├── Question.js
│   │   ├── data.js
│   │   └── index.js
│   ├── Result.js
│   ├── Reviews
│   │   ├── Navigation.js
│   │   ├── Review.js
│   │   ├── data.js
│   │   └── index.js
│   ├── Steps.js
│   ├── Study
│   │   ├── Footer.js
│   │   ├── Lessons.js
│   │   └── index.js
│   ├── data.js
│   └── index.js
├── Header.js
├── Helmet.js
├── Home
│   ├── Courses.js
│   ├── YouTube
│   │   ├── index.js
│   │   └── [email protected]
│   ├── data.js
│   └── index.js
├── Navigation.js
├── Payment
│   ├── Gift
│   │   ├── Telegram.svg
│   │   ├── [email protected]
│   │   └── index.js
│   ├── copy.svg
│   ├── fb.svg
│   ├── index.js
│   ├── ok.svg
│   ├── tw.svg
│   └── vk.svg
├── ReactRemarkable
│   ├── components.js
│   ├── index.js
│   └── toc
│       ├── index.js
│       └── utils.js
├── ScrollToTop.js
├── analytics.js
├── api.js
├── fonts
│   ├── GraphikLCG
│   │   ├── GraphikLCG-Black.eot
│   │   ├── GraphikLCG-Black.ttf
│   │   ├── GraphikLCG-Black.woff
│   │   ├── GraphikLCG-Bold.eot
│   │   ├── GraphikLCG-Bold.ttf
│   │   ├── GraphikLCG-Bold.woff
│   │   ├── GraphikLCG-Medium.eot
│   │   ├── GraphikLCG-Medium.ttf
│   │   ├── GraphikLCG-Medium.woff
│   │   ├── GraphikLCG-Regular.eot
│   │   ├── GraphikLCG-Regular.ttf
│   │   ├── GraphikLCG-Regular.woff
│   │   ├── GraphikLCG-Semibold.eot
│   │   ├── GraphikLCG-Semibold.ttf
│   │   └── GraphikLCG-Semibold.woff
│   └── KazimirText
│       ├── KazimirText-Roman.eot
│       ├── KazimirText-Roman.ttf
│       └── KazimirText-Roman.woff
├── index.css
├── index.js
├── registerServiceWorker.js
└── ui
    ├── Aside.js
    ├── Button.js
    ├── Code.js
    ├── H1.js
    ├── H2.js
    ├── H3.js
    ├── H4.js
    ├── HeroUnit.js
    ├── Link.js
    ├── P.js
    ├── Wrapper.js
    └── index.js