All streams
Search
Write a publication
Pull to refresh
24
0
Andrew Ka @comerc

#кодеротбога

Send message

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

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


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


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

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

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

Форма
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))
    //...
  },

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

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

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


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

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

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


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

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

RSK убивает загрузкой новой страницы браузера при начальной сборке

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

Добавление поста не работает, да и выглядит паршиво. Не удалось реализовать за 15 минут?

На это ушло три недели, и ещё есть над чем работать. Тынц.

Нужно добавить, что Intel XDK помогает разрабатывать на Phaser под мобильные платформы.

отдельное спасибо за memoizee, lodash.memoize работает "иначе":


import memoizee from 'memoizee'
import memoize from 'lodash.memoize'

const test1 = memoizee((a, b, c) => (d) => {
  console.log('test1', a, b, c, d)
})
const a1 = test1(1,2,3)
const b1 = test1(1,2,3)
const c1 = test1(1,2,4)
console.log('a1 === b1', a1 === b1) // a1 === b1 true
console.log('a1 === c1', a1 === c1) // a1 === c1 false
a1(1) // test1 1 2 3 1
b1(2) // test1 1 2 3 2
c1(3) // test1 1 2 4 3

const test2 = memoize((a, b, c) => (d) => {
  console.log('test2', a, b, c, d)
})
const a2 = test2(1,2,3)
const b2 = test2(1,2,3)
const c2 = test2(1,2,4)
console.log('a2 === b2', a2 === b2) // a2 === b2 true
console.log('a2 === c2', a2 === c2) // a2 === c2 true - как-так-то?
a2(1) // test2 1 2 3 1
b2(2) // test2 1 2 3 2
c2(3) // test2 1 2 3 3 - как-так-то?

неправильно! оборачивать нужно снаружи и применять memoizee (почему — смотри коммент выше)

Продолжительные по времени действия… еще лучше реализовать всю архитектуру через events — в таком случае явные асинхронные вызовы вообще не нужны

Куда можно сходить посмотреть примеры?

К сожалению, поддержка HTML в React является неполной. Разработчик должен вручную заменить class на classname, а for на htmlFor. Кроме того, синтаксис встроенных стилей необходимо поменять с CSS на JSON.

styled-jsx? Не, не слышал.

Такой легкий компонент очень удобен при создании простых веб-страниц. Однако, когда требуется взаимодействие между несколькими компонентами, неизбежна передача функций обратного вызова (callback functions) в качестве параметра. В частности, для веб-страниц со сложными структурами приходится использовать десятки взаимосвязанных компонентов, в которых коллбэки передаются от родителей к потомкам из слоя в слой. Единственным результатом применения фреймворка React в таких сложных интерактивных веб-проектах будет то, что код станет слишком беспорядочным и трудноподдерживаемым.

Flux? Не, не слышал.

Сегодня выложили видео доклада https://youtu.be/1RMhUPsVw2M

Поправка — килодолларов.

selectize облегчает страдания, но ненадолго.

Information

Rating
Does not participate
Registered
Activity