Как стать автором
Обновить

Комментарии 44

что разделение на components и containers — это лишнее

Все-таки контейнеры — это view-controllers. Они определяют что именно читать из стора, какие именно действия использовать. Это главное и важное различие.

уважаемый автор признаётся в сносках, что концепция разделения спорная, и компоненты можно смешивать

Мне кажется, это больше касается использования state в компонентах, и элементов, стилей в контейнерах.
RSK убивает загрузкой новой страницы браузера при начальной сборке

это можно отключить в настройках browserSync, добавь open: false в start.js после proxy: {...}

в CRA это тоже можно отключить, package.json:


{ 
  "scripts": {
    "dev": "BROWSER=none npm start",
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

$ yarn dev

Отличное продолжение, интересно почитать!


А почему отказались от идеи повторить дизайн Хабра? На Material-UI получилась очередная поделка, которых в интернете уже куча и до них особо дела никому нет.

Отличное продолжение, интересно почитать!

Спасибо! Очень приятно. 3 недели усердного труда.


А почему отказались от идеи повторить дизайн Хабра?

Чтобы прикрутить Material-UI. :) Хотелось бы получить из коробки более проработанные элементы формы. Планируется стилевая мимикрия, в зависимости от родительского сайта, к которому будет подключаться блог. По этому вопросу всё будет хорошо.

По-моему, MDL (material-design-light) и более зрелый. Не знаю, обернуты ли компоненты для react, например для angular2 они есть точно. А вот к Electrode надо присмотреться, похоже может выручать.

MDL переродился в Material Components for the web. Компонентов меньше, чем в Material-UI. Печалит BEM внутри. Обертка для React-а слабенькая — "Doesn't use MDC JS sources". В морг.


Потенциально интересен react-polymer, но пока не вижу в своём проекте.

А вот к Electrode надо присмотреться, похоже может выручать.

Сначала он мне тоже понравился. Больше того, NEXT.js произвел отрицательное впечатление. Но я уже переобулся, пощупав обе платформы. Можно попробовать перетащить:


А чем в итоге electrode не понравился, и почему самый лучший в итоге это CRA? Может вообще SSR вручную каждый раз из бойлерплейта лучше всего делать?
Как верно сказали выше — сайт на material design выглядит как мертвая поделка. Но плюсов много.

Material-UI позволяет получить ужасный, но сразу кликабельный и рабочий прототип. Часто дизайнеру работать с прототипом быстрее и проще, т.к. понятен UX, есть и данные, и состояния.

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

Как представлю — ужасаюсь. Я храню в одной папке всё, что связано с отдельным модулем приложения: его компоненты (как контейнеры, таки презентационные), его сторы, его гейты к апи, его стили и т. п. По сути получается, что каждый модуль такое мини-приложение, которое с остальными слабо связано.

Когда проект вырастит, следует дробить его на приватные npm-пакеты, инкапсулируя реализацию. Но не выращивать дерево подпапок внутри папки компонентов — развивать и поддерживать такое ощутимо сложнее. Проверено.

Я вижу смысл в выделение в npm (или любой иной) пакет только того, что используется в нескольких проектах, иначе усилия по поддержке пакета не стоят выделки — плавали, знаем. И у меня нет папки компонентов, есть папки модулей приложения, сгруппированные по, прежде всего, предметной области.

Глянуть бы одним глазком на конкретный пример.

Примерно так:
src/Person — папка модуля "физлица"
src/Person/person.js — модель физлица
src/Person/PersonCard.js — карточка физлица (контейнер)
src/Person/PersonCardView.js — карточка физлица (тупой компонент)
src/Person/PersonPhoto.js — фото физлица (контйнер)
src/Person/PersonPhotoView.js — фото физлица (тупой компонент)
src/Person/person.sccc — стили
src/Person/tests/… тесты


Таких модулей несколько десятков, подавляющее большинство задач в рамках одного модуля

Обособить по модулям != устраивать иерархии из компонентов. Это ад. Проходили.

Если положить туда еще package.json, то получится приватный пакет, который можно дергать только через его API (по соглашению). Идея в полной изоляции внутренней реализации. А то я видел примеры, когда из одного пакета объявляют импорт напрямую в другой.


Пример package.json, весь фокус в опции main:


{
  "name": "Person",
  "version": "0.0.1",
  "private": true,
  "main": "./Person.js"
}

А разве не надо будет его переносить из src/ в node_modules, прописывать в package.json и выделять в отдельный репозиторий (хотя бы гит)?


Ну и не вижу особой разницы между import PersonCard from '../Person/PersonCard' и import {PersonCard} from 'person';

А разве не надо будет его переносить из src/ в node_modules, прописывать в package.json и выделять в отдельный репозиторий (хотя бы гит)?

Просто соглашение внутри проекта. Модули складываются в отдельную папку modules, но в папке модуля не нужно объявлять index.js, в котором экспортируется API, а вместо index.js — файл совпадающий с именем модуля, благодаря опции main в package.json (это в частности нужно для Find Usage в WebStorm).


Далее у меня настроены абсолютные пути, по соглашению можно обращаться только к имени модуля: import { PersonCard } from 'modules/person'


Но импорт компонента только для внутреннего использования:
import PersonCardView from 'modules/Person/PersonCardView' — приведёт к анархии, модуль вовсе не модуль (в смысле сокрытия реализации).

Надо будет попробовать, хотя пока сильного практического смысла не вижу.

Декомпозиция + инкапсуляция.

Что пакет redux-form не нужен

Только что закончил проект с реально монструозными и очень динамическими формами (на сотни полей), и просто не представляю насколько сложнее это было бы без redux-form, вообще не имею претензий к этой библиотеке и её производительности. Какие у вас были проблемы? Часто забывают сбилдиться в релиз, отключить redux-devtools и
immutable state invariant, эти вещи отлично помогают в разработке, но легко могут просадить производительность в сотню раз.
Форма
const PostForm = ({
  id, flow, title, content, hubs, isTranslation, sourceAuthor, sourceLink,
  isTutorial, searchHub, sourceFlows, sourceHubs, errors, isLoading, mainError,
  input, save
}) => (
  <div className={s.root}>
    <div className={s.container}>
      <h1>{!!id ? 'Редактирование публикации' : 'Хочу разместить публикацию'}</h1>
      <form onSubmit={handleSubmit(isLoading, save)} autoComplete="off">
        <PostFormIsTutorial {...{ isTutorial, input }} />
        <PostFormFlow {...{ flowId: flow.id, sourceFlows, input, error: errors.flow }} />
        <PostFormTitle {...{ title, input, error: errors.title }} />
        <PostFormContent {...{ content, input, error: errors.content }} />
        <PostFormSearchHub {...{ searchHub, sourceHubs, hubs, input, error: errors.searchHub }} />
        <PostFormHubs {...{ hubs, input, error: errors.searchHub }} />
        <PostFormIsTranslation {...{ isTranslation, input }} />
        <PostFormSourceAuthor {...{ sourceAuthor, isTranslation, input, error: errors.sourceAuthor }} />
        <PostFormSourceLink {...{ sourceLink, isTranslation, input, error: errors.sourceLink }} />
        <PostFormSubmit {...{ isLoading }} />
      </form>
      <br/>
      {!!mainError && <div>{mainError}</div>}
    </div>
  </div>
)

Валидация с зависимыми полями
const required = value => value ? null : 'Required'
const maxLength = max => value =>
  value && value.length > max ? `Must be ${max} characters or less` : null
const range = (value, min, max) =>
  value && value.length >= min && value.length <= max ? null : `Must be from ${min} to ${max} elements`

const validators = {
  flow: (value) => required(value.id),
  title: (value) => required(value) || maxLength(POST_FORM_TITLE_MAX)(value),
  content: (value) => required(value),
  searchHub: (value, state) => {
    const hubs = state.postForm.hubs
    return required(!isEmpty(hubs)) || range(hubs, 1, POST_FORM_HUBS_MAX)
  },
  sourceAuthor: (value, state) => {
    return state.postForm.isTranslation && required(value)
  },
  sourceLink: (value, state) => {
    return state.postForm.isTranslation && required(value)
  },
}

Обработки onInupt
  input: ({ key, value, isValidate = false }) => (dispatch, getState) => {
    if (isValidate) {
      const validate = validators[key]
      if (!!validate) {
        const state = getState()
        const error = validate(value, state)
        if (state.postForm[key] !== error) {
          dispatch(setError({ key, error }))
        }
      }
    }
    if (value !== void 0) {
      dispatch(setField({ key, value }))
    }
  },

Обработка onSubmit
  save: () => (dispatch, getState) => {
    const state = getState()
    const errors = {}
    Object.keys(validators).forEach(key => {
      const validate = validators[key]
      const error = validate(state.postForm[key], state)
      if (!!error) {
        errors[key] = error
      }
    })
    if (!isEmpty(errors)) {
      dispatch(setErrors(errors))
      dispatch(appActions.setMainError('Исправьте ошибки в форме'))
      return
    }
    dispatch(appActions.setMainError())
    dispatch(appActions.setLoading(true))
    //...
  },

Скрипач не нужен. :)

Ну так у вас простая форма, и при этом одна, тут и вправду не сильно нужен redux-form. Он нужнее там где форм много, и все они сложные.

на самом деле нет.


Чем больше форма и проект, тем больше выскакивает косяков из-за необновления каких-то полей в модели. Вот два примера из моей практики:



По итогам всего этого могу сказать, что лучше держать логику обработки форм у себя в проекте. Если он действительно большой, то это будет меньше 10% вашего кода и много сил на поддержку не отнимет. Гораздо проще будет, чем подкладывать костыли под redux-form.

Несмотря на большую сложность, вложенность и динамичность — обошлось без костылей, и всё работает именно так как задуманно.

Вам повезло, что ваши требованиями по фичам совпали с возможностями redux-form, рад за вас.


Однако приведенные мной ссылки — это открытые баги, а значит они есть, и когда вы с ними столкнетесь, вам придется либо форкать redux-form либо съезжать на другое решение для форм.

Либо делать пулл реквест, что всяко быстрее написания всего функционала с нуля. Мои PR-ы проходили довольно быстро. Правда и правки были минимальными.

React-MD не видел, очень даже. Компонентов больше. Но стилевая мимикрия будет сложнее.

React Toolbox ещё вполне себе, но требует поддержки CSS Modules в проекте, к сожалению.

Есть react-toolbox-themr.
Добавляем себе в проект, вешаем его на postinstall и он будет собирать стили для toolbox сразу после его установки. В своем конфиге вебпака ничего хачить не надо.


Приятным бонусом будет еще и то, что теперь можно называть свои css-классы как угодно и не бояться что они перекроют что-то из библиотеки.

Не совсем понял смысл next.js. Как мне кажется один из плюсов приложений на js — было то что рендеринг отдается на откуп клиенту, и серверу нужно только через апи отдать нужные данные.

Серверный рендеринг для двух вещей нужен:


  • отдать клиенту отрендеренную страницу с нужными ему данными, а уж потом он будет рендерить полученные дополнительно через апи данные — сочетаем плюсы серверного рендеринга (быстрый показ при первом открытии приложения) и клиентского (при дальнейшей работе с приложением рендерит уже клиент, а сервер только данные по апи отдаёт/принимает)
  • отдавать поисковикам и прочим ботам отрендеренные страницы для SEO, превьшек на ссылки и т. п.

Смысл серчать на redux-froms тыкая на ~450 issues в то время как bug-labeled всего лишь 23 ?!
Вас же реакт со своими 572 issues не остановил, а там то bug-labeled побольше будет — аж целых 37(!)


С таким же успехом можно было бы сравнивать по количеству звёзд на гитхабе, детский сад какой-то.


P.S. С redux-froms не работал

Абсолютными числами оперировать некорректно. Лучше взять процент.


В react 572 из 3669 (15%)
В redux-form 465 из 1732 (26%)


Иными словами, четверть запросов пользователей остается без ответа. Учитывать только баги тоже некорректно, так как отсутствующие фичи это тоже проблема

А вообще, вы правы.


Осознание, что redux-form не торт пришло после месяца работы с ним. Как это предвидеть заранее — непонятно.

А чем не торт? Я после проекта законченного за три месяца понял что без redux-form делал бы этот проект на три месяца дольше.

Мы уже общались в этой ветке и я рассказал о незакрытых issues, под которые пришлось искать костыли.

Упс, я подумал что вы новый человек. Ну всё-же незакрытые issues под довольно специфичные действия — не такой уж большой показатель. Вы всегда можете заинвестигейтить в чём дело и сделать свой pull request, библиотека всё-такие бесплатная и с открытым исходным кодом.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации