Swizec Teller - a geek with a hatswizec.com

    Backbone → React: it's a people problem after all ?

    The Big Scary Refactor™, turning a largish, hard-to-manage Backbone app into an easier to manage React app… it got off to a great start yesterday. Today, not so much.

    First of all, I realized that our problem isn’t Backbone. The problem is that our UI is not a function of state. It’s an expression of state and a sequence of user actions.

    https://twitter.com/Swizec/status/778300885017296896

    To give you a simple example, we use this pattern a lot:

    class Thing extends Backbone.View {
    constructor() {
    this.events {
    "click button": "toggleActive"
    }
    }
    toggleActive() {
    if (checkSomething) {
    this.$('button').addClass('active');
    }else{
    this.$('button').removeClass('active');
    }
    }
    }

    This is a trivial Backbone view. It listens for a click event on a <button>. When a click happens, it either adds or removes an active class on that button.

    Our real views do the same sort of thing, but on a grander scale. It might seem harmless enough, but if your code has this pattern, you can’t reliably wrap Backbone views in React components. You’d have to replay all user interaction on every re-render.

    That’s a no-go.

    A better approach, which we follow most of the time (but of course not all of the time), is to move that checkSomething into the View’s backing Model. Something like this:

    class Thing extends Backbone.View {
    constructor() {
    this.events {
    "click button": "toggleActive"
    }
    this.model = new Backbone.Model({active: false});
    this.listenTo(this.model, 'change', this.render);
    this.template = Handlebars.compile('<button class={{#if active}}active{{/if}}>Button</button>');
    }
    toggleActive() {
    this.model.set('active', !this.model.get('active'));
    }
    render() {
    this.$el.html(this.template(this.model.attributes));
    }
    }

    Now the UI is an expression of state and user actions manipulate that state instead of the UI. You can re-render as much as you want, and your UI will look correct.


    But why re-render in the first place? Because it’s the easiest way to deal with data changes from above.

    We’re moving towards a modern unidirectional data flow architecture where application state lives in a central Redux or MobX store. Right now, it’s scattered through a bunch of Backbone Models living inside each View individually. Then they interact.

    It’s a mess. Did I mention we have untraceable heisenbugs? Many.

    If you want unidirectional, then The Central Store is your single source of truth. That means that when new state comes down from the top, you follow.

    With a React component, your props change, React calls render(), and your UI updates.

    When your React component is just a thin wrapper for a Backbone View, well… then you have a choice. Update the view’s internal model and hope for the best, or throw the view away and render a new one… and once again hope for the best.

    There’s a lot of hoping for the best, but I think the “throw away and re-render” is going to be easier to deal with in the long run. It’s also better when we go through the process and all those child Backbone Views eventually become proper React components.

    Replaying user interaction to exactly match UI on re-render? Yeah, fuck that. That’s not gonna work with either strategy. ?

    Ok, so we have our first tradeoff: To avoid UI staleness, we’re going to have UI that forgets user interactions.

    Such is life ¯\_(ツ)_

    Tomorrow, I’ll show you why I think MobX can’t work in our situation, but Redux might.

    PS: If you wanna help, we’re hiring. Ping me.

    Did you enjoy this article?

    Published on September 21st, 2016 in backbone, backbonejs, Front End, react, reactjs, Technical,

    Learned something new?
    Want to become an expert?

    Here's how it works 👇

    Leave your email and I'll send you thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths.

    Join Swizec's Newsletter

    And get thoughtful letters 💌 on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.

    "Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"

    ~ Ashish Kumar

    Join 15,161+ engineers just like you already growing their careers with my emails, workshops, books, and courses.

    ⭐️⭐️⭐️⭐️✨
    4.5 stars average rating

    Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.

    Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.

    Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.

    Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev

    Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization

    Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections

    Want to brush up on modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog

    Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

    By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️

    Created by Swizec with ❤️