From Swift to React: A Wake-Up Call in the World of Web Apps
Home Blog Post Details

I’ve spent a good part of my career building delightful experiences on iOS. Swift, UIKit, clean architecture, and strong separation of concerns have always been part of my toolkit. It’s a world where structure and clarity are expected—almost second nature.

So when I stepped into web development, I was excited. The browser! JavaScript! React! A new world with endless possibilities.

And then… reality hit.

The Bloat Was Real

The first thing that caught me off guard was how bloated React components could get.

In Swift, you’d rarely find a `UIViewController` with 300+ lines of code doing everything from UI rendering to data formatting to API calls. But in React? It was everywhere.

I’d open a component file expecting to see just the UI... and instead be greeted with a mix of logic, state management, network calls, and conditional rendering—all crammed into a single `render()` function or `return` block.

It felt like those horror stories of massive `ViewController.swift` files that we’ve been taught to avoid from day one on iOS.

Where's the Separation?

Coming from an MVC/MVVM background, separation of concerns was muscle memory for me. But in many web codebases, it felt like everything was mashed into one.

Component files weren’t just components—they were routers, data fetchers, and sometimes full-on state machines. The idea of having clearly defined layers—UI, business logic, networking—was often ignored, if not entirely absent.

To be fair, this wasn’t React’s fault. React is flexible. But that flexibility can be a double-edged sword if a project lacks conventions or structure. I quickly learned that you can write React code in any way you want—and sometimes, that’s the problem.

Unit Testing? Good Luck.

Testing in iOS was second nature to me. I could mock dependencies, isolate logic, and test without even spinning up a view.

But in some React projects, unit testing felt like an afterthought—or worse, an impossibility. When components are tightly coupled to both data-fetching and UI logic, writing clean, isolated tests becomes a mess.

Without proper separation and modularity, I found myself thinking, “Do I need to render the entire DOM just to test this conditional?”—something that felt absurd coming from Swift land.

The Data Prop-Drilling Nightmare

And then there was prop drilling.

Passing data from parent to child, then to grandchild, and on and on—just to get a user ID into a deeply nested component. In Swift, we’d use delegation, bindings, or dependency injection. In React, especially in older codebases, this often meant threading the same props through five layers of components.

It felt like plumbing. And not the elegant kind.

Sure, tools like Context and Redux can help. But again, only if the codebase uses them properly—and early on, I saw a lot of projects that didn’t.

How I Fixed It

Once I recognized the patterns that were holding the codebase back, I began introducing structure—borrowing heavily from the iOS world.

MobX State Tree became my go-to for state management. It felt familiar—reactive, observable, and modular—almost like `Combine` or `RxSwift`. It allowed me to create centralized stores for business logic, keeping React components clean and focused on UI alone.

I also put a strong emphasis on building reusable, composable components, avoiding massive files with logic tangled inside the render method. Instead of dumping everything into one `render()` block, I broke things down into smaller, readable components with clear responsibilities.

This approach didn’t just make the code easier to test—it made it a lot more enjoyable to write and maintain. Unit tests became simpler once the logic lived in testable stores instead of tangled inside the UI layer.

What I Learned

Despite all the frustrations, this experience taught me a lot.

  • React gives you freedom, but with freedom comes the need for discipline.
  • Clean architecture is just as important in web as it is in mobile—maybe more.
  • Conventions and code quality matter. Without them, the developer experience (and team productivity) quickly falls apart.
  • Bringing ideas from mobile—like separation of layers, composable views, and clear testing boundaries—can vastly improve a React codebase.
  • Familiar tools like MobX, when used right, can bridge the gap between platforms and make the transition smoother.
Final Thoughts

Moving from iOS to web development was a humbling experience. It exposed assumptions I had made about how teams approach architecture and quality.

But it also gave me an opportunity: to bring lessons learned from years of mobile development into a world that sometimes prioritizes speed over structure.

If you're an iOS dev thinking of making the jump, be ready to unlearn some things—but don’t leave your instincts behind. The web could use more of that thoughtful engineering mindset.

And if you're a React dev who's never looked at mobile code? Maybe it's time to borrow a few pages from the iOS playbook.

You’d be surprised how much they can help.