If not using “React”

Colleagues from the side of the backend sometimes kindly ask: “what the hell do you need react for here”? Let’s be honest and answer that without it, you can write pretty decent code, give it to a full-stack colleague for review and get an approval after 15 seconds (so fast, not because the colleague is not worried about the quality of the code, but simply the code is very compact, see below) . If you think a little longer (for example, in the time of brewing tea, which, as everyone knows, is equal to three minutes), you can find at least six errors, and maybe more. Any mistake is, of course, very subjective, but I will try to objectively explain each of them.

The code below is a regular list with an “add” button, the code is working in the sense that it can be copied to a file and opened in a browser.

<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>

So the errors are:

  1. Let’s start with perhaps the most innocuous – Array.join in the template method. Here, it’s not the property of the component to convert between an array and a string for rendering. [jsx]

  2. Redraw the entire screen when an element is added. Intuitively, I want to finish, not redraw 🙂 [virtual dom]

  3. Forced inaccuracies with subscriptions – calling unsubscribe (resource method) here and there. It can be argued that in this example unsubscribe is not needed in the render, as we can call clear next, but in this case we, unfortunately, lose the idempotence of the render (see plz https://en.wikipedia.org/wiki/Idempotence) [lifecycle]

  4. Reference to themselves in the callback. It’s a good question here how bad it is for the V8 engine, but intuitively creating a cycle of links is not a good idea. [тут тег, в котором реакт не одобряет такое]

  5. Creating a component for each callback. There may be nothing wrong with this, but this action increases the entropy (about understanding the program) as a whole rather than reduces it. [state observers]

  6. Manual cleaning of resources (the clear method must be called from outside), as a result, it is easy to forget or lose something. [ownership]

  7. And finally, the question of the composition of such components – but this, as in the most average project, is usually thought about later.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *