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

Если не использовать «React»

Время на прочтение2 мин
Количество просмотров13K

Коллеги со стороны бакэнда иногда любезно спрашивают: "а нафига вам тут реакт"? Будем честны и ответим, что без него можно написать довольно приличный код, отдать его на ревью коллеге-фулстеку и получить аппрув после 15 секунд (так быстро не потому, что коллега не беспокоится за качество кода, а просто код весьма компактен, cмотрите ниже). Если подумать чуть-чуть дольше (например, за время заварки чая, которое, как все знают, равно трем минутам), можно найти не менее шести ошибок, а может и больше. Любая ошибка, конечно, весьма субъективна, но я постараюсь объективно объяснить каждую из них.

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

<body>
<script>  

class Component {
  constructor(
    container,
    callback, // callback on add
    emails = [], // state 
  ) {
    this.container = container;
    this.callback = callback;
    this.emails = emails;
  }

  templateForOneEmail(title, body) {
    return `
      <h4>${title}</h4>
      <div>${body}</div>
      <hr />
    `;
  }

  template() {
    const str = this.emails
      .map(([title, body]) => this.templateForOneEmail(title, body))
      .join("");
    return `
      <div id="my-emails">${str}</div>
      <button id="my-button">Add</button>
    `;
  }

  subscribe() {
    const node = this.container.querySelector("#my-button");
    if (node) 
      node.addEventListener("click", this.callback);
  }

  unsubscribe() {
    const node = this.container.querySelector("#my-button");
    if (node)
      node.removeEventListener("click", this.callback);
  }

  render() {
    this.unsubscribe();
    this.container.innerHTML = this.template();
    this.subscribe();
  }

  clear() {
    this.unsubscribe();
    this.container.innerHTML = "";
  }
}


function main() {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const emails = [];

  let comp = null;
  const callback = () => {
    if (!comp) { return; }
    emails.push(["title", "body"]);
    comp.clear();
    comp = new Component(container, callback, emails);
    comp.render();
  }
  comp = new Component(container, callback, emails);
  comp.render();
}

main();

</script>
</body>

Итак, ошибки:

  1. Начнем, пожалуй, с самой безобидной - Array.join в методе template. Вот, не свойство компонента конвертировать между массивом и строкой для рендинга. [jsx]

  2. Перерисовка всего экрана при добавлении элемента. Интуитивно хочется дорисовать, а не перерисовать :) [virtual dom]

  3. Вынужденные неточности с подписками - вызов unsubscribe (ресурсный метод) то тут, то там. Можно возразить, что в данном примере unsubscribe в рендере не нужен, так как мы можем вызвать clear следом, но в этом случае мы, к сожалению, теряем idempotence рендера (см. плиз https://en.wikipedia.org/wiki/Idempotence) [lifecycle]

  4. Ссылка на самих себя в колбеке. Тут хороший вопрос, насколько это плохо для движка V8, но интуитивно создание цикла из ссылок не очень хорошая идея. [тут тег, в котором реакт не одобряет такое]

  5. Создание компонента на каждый колбэк. Тут, возможно, и нет ничего плохого, но данное действие, скорее, увеличивает энтропию (о понимании программы) в целом, чем уменьшает ее. [state observers]

  6. Ручная чистка ресурсов (метод clear нужно вызывать извне), как следствие, легко что-то забыть или потерять. [ownership]

  7. И напоследок, вопрос о композиции таких компонентов - но это, как и на самом среднем проекте, обычно думается потом.

Теги:
Хабы:
Всего голосов 14: ↑2 и ↓12-8
Комментарии27

Публикации

Истории

Работа

Ближайшие события

Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область