Pull to refresh

Comments 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? Он по определению не знает, что нужно дочернему компоненту в общем случае, если и использует собственные атрибуты, то все остальные должен передать как есть.
Sign up to leave a comment.

Articles