Как стать автором
Поиск
Написать публикацию
Обновить

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

Про key забыли.


<ul>
  {["first", "second"].map((item) => (
    <li>{item}</li>
  ))}
</ul>

<ul>
  {[
    <li>first</li>,
    <li>second</li>,
  ]}
</ul>

Будет предупреждение:


Warning: Each child in an array or iterator should have a unique "key" prop. See https://fb.me/react-warning-keys for more information.
да, конечно, просто тут не об этом…
И еще немного о Destructuring Arguments:

const {id: someIdInData} = data
console.log(id)
Только правильно так (имя переменной в которую попадет значение, указывается справа от двоеточия):
const {id: someIdInData} = data
console.log(someIdInData)
Stateless functions — очень удобная в быту штука. Но, к сожалению, пока не умеет shouldComponentUpdate для того, чтобы проверить самому props, сделать short circuit и не рендерить всех детей. А было бы классно, в некоторых случаях top-down rendering стал бы ну очень простым и дешевым.
Но вроде бы обещают сделать.
Не очень понятно, что имеешь ввиду, можешь более развернутый пример привести?
О, ну тут всё достаточно просто.
Что происходит, когда надо перерисовать компонент? Вызывается метод shouldComponentUpdate(nextProps, nextState): Boolean.

Если метод вернет false, то всё дерево компонентов, которое строится в результате работы метода render() останется нетронутым — это называется short circuit. Т.е. ты как-бы говоришь реактовскому движку «спокойно парень, я уверен, ничего не изменилось», и реакт пропускает целиком все поддерево, которое растет из этого компонента.

Если метод вернет true, то реактовский движок вызовет метод render, сверит результат и если что-то изменилось, то начнется reconciliation, который сам по себе отдельная история.

Мораль: правильно написанный (но не всегда :) ), shouldComponentUpdate может сильно ускорить перерисовку.
И вот этого метода в functional components нету, хотя было бы круто, если бы был.

тут на помощь может прийти recompose c хелпером pure:


import pure from 'recompose/pure';

function MyComponent() {
   return <div>I am pure!</div>
}

export default class pure(MyComponent);

В целом — да, но в принципе такой штуки можно и достичь простой оберткой function -> react class. Но за ссылку спасибо.

Может наоборот — react-class который оборачивает функцию?


Если нет, то можно посмотреть пример, как это делается?

По поводу Children pass-thru:

Лучше всего управлять потомками при помощи специальных методов — React.Children. Например пример ниже позволяет вернуть только потомков и не требует дополнительной обертки

return React.Children.only(this.props.children)


Это лишь способ указать, что children железно должен быть одним элементом в любом случае. Иначе React бросит исключение. Это никак не возможность вернуть несколько дочерних элементов напрямую, без оборачивающего элемента. Пример выше лишь проверит, что потомок один и вернет его.

В статье с названием "паттерны React" всего один паттерн (stateless component) и один антипаттерн (event switch), ну за уши можно притянуть еще и "Higher-order component", что, вообще-то говоря, некое подобие карринга, а, главное, является основами JS в секции "замыкания". Остальное — либо непонимание ООП (Container component), хотя, в целом, это ближе к паттерну "провайдер" (https://en.wikipedia.org/wiki/Provider_model), либо возможности es2015+ или jsx.


Теперь конструктивно по пунктам:


  1. Про stateless function, она же "глупый компонент", "глупое представление" и "чистая функция" (в очень вольной интерпретации) сказано про её красоту, но не сказано главное преимущество, ведь действительно, всем плевать на производительность, когда можно писать так, в пару строк, без всяких там классов. А именно — у нее есть автоматический shouldComponentUpdate, который всегда сверяет — изменились ли переданные параметры или нет, что делает использование этого синтаксиса крайне желательным и удобным, покуда позволяет повысить производительность без лишних строк кода (проверки параметров вручную), но накладывает ограничение — параметры сверяются через ===, т.е. если изменилось какое-то свойство объекта, а не сам объект (объект передался по ссылки по-прежнему), компонент не перерисуется, будете гадать потом почему. Хорошо работает в купе с immutable.


  2. JSX Spread Attributes. Object.assign для ленивых, но нужно признаться, что очень удобный функционал. Более того, он так же работает и в js, так что можно писать что-то в стиле const options = {someDefaultValue: true, anotherValue: false, ...passedOptions};. Только не забываем подключить preset: react в babel.


  3. Conditional Rendering. Зло, best practices — выносить подобные вещи в константы и определять их до функции return. Например:


    const warningMsg = hasWarning && <div>warning: {warning}</div>;
    return (<div>
    {warningMsg}
    </div>);

  4. Ну и да. ЧЕГО? Какой conditional renderig? Тут просто стандартные возможности js (еще в далеком 2007 писали var something = param.something || default) + основы JSX в виде рендера того, что находится в фигурных скобках.


  5. Children Types. Ложь, кроме как строки, Number, Boolean и React node, а так же массива из этого, (с недавних, вроде как с 0.14 версии, еще и null) ничего он рендерить не умеет. На попытку отрендерить обычный объект ругнется Error: Objects are not valid as a React child. Вдобавок, это эм документированная (но автор документацию явно не читал) и основная, как шаблонизатора, возможность JXS, давайте как паттерны может быть еще и то, что в JS можно два числа складывать напишем?


  6. Children pass-through. Опять же есть в документации и является частью библиотеки. Однако будте предельно осторожны с этой функцией, можно напороться, что он по той или иной причине не перерендерит.


  7. Event switch. Антипаттерн, имеющий целый вагон проблем. Одна из основных — IDE вам тут никак не поможет, а вместо ENUM или хотя бы констант используются строки, шанс ошибиться велик. Вторая — масштабируемость и расширяемость. Вообще задание "перепишите код с switch таким образом, чтобы его было легко изменять и расширять" — типичное тестовое задание для junior, что как бы намекает, что так лучше не делать. Ну и да, полностью ломает ООП, че уж.


  8. Layout component. Используйте в нем shouldComponentUpdate с умом и крайней осторожностью, потому что если вы захотите передавать сквозь него какие-то параметры в дочерние элементы из "умного компонента" вниз в "глупые", то из-за принудительного false в shouldComponentUpdate ничего перерисовываться не будет.


  9. Higher-order component: я уже говорил, что это карринг, а так же основы js, не понятно, по какой причине они бы не срабатывали в JSX.

Это были замечания к автору. Замечания к переводчику: promt образца 2007 года detected. Каждое второе предложение переведено настолько странно, что если кидать в личку — исправлений наберется на вторую такую же статью.


Однако, как ни странно, статья неплохая и в ней много полезного, осталось это привести к человеческому виду.

Дико извиняюсь. По первому пункту я телепортировался в будущее, когда это уже сделали. Пока что ничего такого нет, но в документации слезно клянутся, что будет, и что этот синтаксис стоит использовать всегда, когда есть возможность, и в какой-то чудесный момент ваше приложение резко прибавит в скорости (хороший ответ на stackoverflow )

Насчёт 7. switch в javascript зло конечно дикое, но из него можно изобразить что-то вроде паттерн матчинга для бедных. Для очень бедных.


switch(true) {
  case type === "click" && something.isDefined() === true:
    return "It was click";
case type === "mouseenter" && somethingElse.isDefined() === true:
    return "It was mouseenter";
default:
    return console.warn(`No case for event type "${type}"`);

На мой взгляд даже в таком виде это сильно симпатичнее цепочки if-else-if. Но дно достигается, конечно, в момент объявления переменной в любом case. Никакие let и const не спасают — scope у всех один.

Или я не понял, о каком дне вы говорите, или вы { } в case не ставили:
case type === "click": {
      ...
      return;
}

Я вот либо что-то упустил в самых основах, либо это нечто совсем недавно появилось. Но хм… это не создает новой области видимости. Если не сложно, можно ссылку на пример? Вот gist с прямым примером: https://gist.github.com/wertlex/b97115e0f2fe0bc023297f6b2db8edd5

в ес6 (после бабеля) создаёт
У вас в примере то, о чем я говорил. Переменная value есть в обоих case и каждая из них имеет свое значение.
В теории, если я не ошибаюсь, должна создаваться блочная область видимости. Как браузеры делают — не знаю. Babel просто имитирует блочную видимость и в вашем примере переименует второй value в _value, чтобы имена не пересекались.
Это с es2015 пресетом полным он так поступит. Хром уже давно все это умеет без бабеля.Только плагин на импорт-экспорт нужен и все. Только хвостовую рекурсию не умеет из es2015.
А по поводу опечаток, можно собрать все event'ы, приравненные к строке и использовать их как переменные.
Это, кстати, recommended-practice небезызвестного Redux'a хоть и для иных строк.
Вот по п.3 когда она еще константа, а когда ее уже надо в отдельный компонент выделять есть критерии? (речь не о вновь пишущейся константе а от той что с возрастом усложняется)

допустим там у дива класс появился, у ворнинга свое условие и эвент еще какой?

Если это класс и подобное — нет, имеется ввиду наличие или отсутствие или выбор одного из двух элементов. Классы и прочие аттрибуты — тоже желательно считать до рендера, но местами, чтобы не загромождать, можно и инлайново. Если же весь шаблон сделать вот как рекомендует автор (инлайново в шаблоне) — он быстро разрастется и станет нечитаемым. Что касается когда нужно выносить в константу, а когда в отдельный компонент — по мне, так первым сигналом является переиспользование. Если испольуете одно и то же хотя бы в двух местах — уже выносите. Если просто говорить про объем — я не могу сказать какое-то конкретное количество строк, на усмотрение ваше

Согласен с замечаниями, некоторые из пунктов статьи действительно странные (Event switch — в первую очередь).
Остальное пожалуй больше для начинающих, кто в 2007 про var something = param.something || default ничего знал.

JSX Spread Attributes имеет одну проблему, в дочерний компонент может залететь то, что не нужно. И начиная с 15 версии Реакт начинает ругаться на атрибуты, которые не были указаны в PropTypes

А как быть с HOC? Он по определению не знает, что нужно дочернему компоненту в общем случае, если и использует собственные атрибуты, то все остальные должен передать как есть.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации