Chapter 1: The Problem React Claims to Solve (That Wasn’t Really a Problem)

In 2013, Facebook had a problem. Not a “the servers are on fire” problem, or a “we’re hemorrhaging users” problem. No, Facebook had a much more first-world problem: their notification counter was sometimes wrong.

You know that little red badge that shows you have 3 new messages, but when you click it, there’s only 2? That. That was the crisis that birthed React. Somewhere in Menlo Park, engineers were losing sleep because the number in a tiny red circle didn’t match reality for a few seconds.

Let me put this in perspective. In 2013:

  • Healthcare.gov had just launched and literally didn’t work
  • People were still using Internet Explorer 8 in production
  • Mobile websites were barely functional
  • Half the internet still used Flash

But Facebook’s priority? Making sure their notification bubble was always, always accurate. This is like inventing the automobile because your horse occasionally sneezes.

The “jQuery Spaghetti” Myth

Before we dive into React’s origin story, we need to address the great lie that React evangelists love to spread: that before React, we were all writing unmaintainable “jQuery spaghetti code.”

Here’s what jQuery code actually looked like:

// The "Unmaintainable Spaghetti" that somehow powered 
// the entire internet for a decade
$('#submit-button').on('click', function() {
  var username = $('#username').val();
  $.post('/api/login', { username: username }, function(response) {
    if (response.success) {
      $('#welcome-message').text('Welcome, ' + response.name);
      $('#login-form').hide();
      $('#dashboard').show();
    } else {
      $('#error-message').text(response.error).show();
    }
  });
});

Horrifying, right? You can actually understand what it does just by reading it. The button click triggers a login, and then updates the page based on the response. No build step, no transpilation, no virtual DOM diffing algorithm. Just… code that does what it says.

Now here’s the same thing in React (circa 2013):

var LoginComponent = React.createClass({
  getInitialState: function() {
    return {
      username: '',
      error: null,
      isLoggedIn: false,
      userName: null
    };
  },
  
  handleUsernameChange: function(e) {
    this.setState({ username: e.target.value });
  },
  
  handleSubmit: function(e) {
    e.preventDefault();
    var self = this;
    
    fetch('/api/login', {
      method: 'POST',
      body: JSON.stringify({ username: this.state.username }),
      headers: { 'Content-Type': 'application/json' }
    })
    .then(function(response) { return response.json(); })
    .then(function(data) {
      if (data.success) {
        self.setState({
          isLoggedIn: true,
          userName: data.name,
          error: null
        });
      } else {
        self.setState({
          error: data.error
        });
      }
    });
  },
  
  render: function() {
    if (this.state.isLoggedIn) {
      return React.createElement('div', null,
        React.createElement('h1', null, 'Welcome, ' + this.state.userName),
        React.createElement('div', { id: 'dashboard' }, 'Dashboard content here')
      );
    }
    
    return React.createElement('form', { onSubmit: this.handleSubmit },
      React.createElement('input', {
        type: 'text',
        value: this.state.username,
        onChange: this.handleUsernameChange,
        placeholder: 'Username'
      }),
      this.state.error && React.createElement('div', { 
        className: 'error' 
      }, this.state.error),
      React.createElement('button', { type: 'submit' }, 'Login')
    );
  }
});

Look at that beauty. Three times the code to do the same thing, plus now you need to understand:

  • Component lifecycle
  • State management
  • Event binding
  • The render method
  • React.createElement syntax (because JSX didn’t exist yet)
  • How this works in JavaScript (spoiler: nobody really knows)

But hey, at least Facebook’s notification counter was accurate!

Two-Way Data Binding: The Devil We Knew

Before React decided that one-way data flow was the One True Way™, we had frameworks like Angular and Knockout that used two-way data binding. It was simple: your model updates the view, and the view updates the model. Like a conversation between two adults.

<!-- Angular 1.x - The Dark Ages, apparently -->
<input ng-model="user.name">
<p>Hello, !</p>

That’s it. The input and the paragraph are synced. Change one, the other updates. It was so simple that even backend developers could understand it.

React looked at this simplicity and said, “No. What if instead, data could only flow one way, and to update anything, you had to explicitly call a function that triggers a re-render of the entire component tree, which then gets diffed against a virtual representation of the DOM to determine what actually needs to change?”

It’s like replacing a light switch with a Rube Goldberg machine. Sure, the light still turns on, but now you need a Ph.D. to understand why.

Facebook’s First World Problems

Let’s go back to Facebook’s notification problem. Here’s what was happening:

  1. User gets a new message (real count: 1)
  2. Notification badge updates (shows: 1) ✓
  3. User gets another message (real count: 2)
  4. Different part of the app also updates the count (shows: 3) ✗
  5. User clicks notification
  6. Chaos, confusion, existential crisis

The problem wasn’t jQuery. The problem wasn’t the DOM. The problem was that Facebook had grown so large and complex that different teams were stepping on each other’s code. They had an organizational problem, not a technical one.

But instead of saying, “Hey, maybe we should coordinate better,” they said, “Let’s rebuild the entire concept of web development from scratch!”

It’s like burning down your house because you can’t find your keys.

When Simple Became Complex

The real tragedy of React isn’t that it exists - it’s that it convinced an entire generation of developers that the simple ways were wrong. Suddenly:

  • Direct DOM manipulation became “an anti-pattern”
  • Inline event handlers were “bad practice”
  • Global functions were “not the React way”
  • Server-rendered HTML was “outdated”
  • Page refreshes were “jarring to the user”

Here’s a fun exercise. Try explaining to a new developer why this is bad:

document.getElementById('counter').innerHTML = count + 1;

But this is good:

const [count, setCount] = useState(0);
setCount(prevCount => prevCount + 1);

“Well,” you’ll start, “the first one directly mutates the DOM, which means React doesn’t know about the change, so the virtual DOM gets out of sync with the real DOM, and then when React does its reconciliation…”

Stop. Listen to yourself. You’re explaining why directly telling the browser to update a number is worse than maintaining a parallel virtual universe that occasionally syncs with reality.

The Real Problems React Solved

Okay, let’s be fair for a moment. React did solve some real problems:

  1. Component Reusability: Being able to create self-contained components is genuinely useful
  2. Predictable Updates: Knowing when and how your UI will update is valuable
  3. Better Developer Tools: React DevTools are actually pretty nice
  4. Community Ecosystem: The massive ecosystem means solutions exist for most problems

But here’s the thing: we could have solved these problems without throwing away everything we knew about web development. Other frameworks did. Vue took the good parts of React and kept the simplicity. Svelte compiled away the complexity. Even modern vanilla JavaScript with Web Components solves most of these problems.

The Notification Counter Today

Want to know the beautiful irony? Facebook (now Meta) has moved away from the original React architecture. They use React Server Components, Relay, and a bunch of internal tools that most React developers have never heard of. The React you’re learning isn’t even the React that Facebook uses.

And that notification counter? Still occasionally shows the wrong number.

Reality Check: The World Before React

Let’s remember what we could do before React “saved” us:

// Load a page instantly
<a href="/next-page">Next Page</a>

// Submit a form without JavaScript
<form action="/submit" method="POST">
  <input name="email">
  <button>Submit</button>
</form>

// Update content dynamically
element.innerHTML = newContent;

// Handle user interaction
button.onclick = function() {
  doSomething();
};

// Animation without a library
element.style.transition = 'all 0.3s';
element.style.transform = 'translateX(100px)';

These things still work. They’re still fast. They’re still simple. But now they’re “not the React way.”

In Defense of React (Yes, Really)

Look, React isn’t evil. It’s not even bad, necessarily. It’s just… overwrought. It’s like using a sledgehammer to hang a picture frame. Sure, the picture will be on the wall, but you’ve also destroyed the wall.

React makes sense when:

  • You’re building something genuinely complex (like… Facebook)
  • You have a large team that needs strict conventions
  • You’re building a true single-page application
  • Component reusability is crucial to your architecture

React doesn’t make sense when:

  • You’re building a marketing website
  • You need great SEO out of the box
  • Your team includes non-JavaScript developers
  • You value simplicity over “best practices”
  • You want your site to work without JavaScript

The Path Forward

So here we are. React exists because Facebook had a specific problem that required a specific solution, and somehow that solution became everyone’s solution, whether they had the problem or not.

It’s like if one person was allergic to peanuts, so now nobody can eat peanuts, and we all have to eat this synthetic peanut replacement that tastes weird and requires special preparation, but hey, at least nobody’s allergic to it!

In the next chapter, we’ll explore how we got from “React is Facebook’s thing” to “React is the only thing.” Spoiler alert: it involves a lot of blog posts, conference talks, and FOMO.

But first, take a moment to mourn the simplicity we’ve lost. Pour one out for document.write(). Light a candle for inline onclick handlers. Say a prayer for the days when “View Source” actually showed you the source.

Those days are gone. React is here. Resistance is futile.

But at least now you know why.