Sign in
Log inSign up

Why not React

power's photo
power
·Jul 28, 2021·

13 min read

If I'm going to share the big picture with you, I owe it to you to be completely up front about the potential issues with choosing React. So in this module I'll share the common concerns I hear about React. JSX differs from HTML. React requires a build step. There's a potential for version conflicts. And React has evolved over time, so you'll find references to old features when searching the Web. And since React is a lightweight library, you may feel intimidated by the number of decisions you need to make up front. Oh, and you might have heard that React's license has a patent clause. Well, great news that's no longer an issue. With the release of React 16, Facebook re‑licensed React to use the standard MIT open source license. So there's nothing to worry about there anymore. That said, you'll see that some of the other concerns above are valid and others are merely misconceptions or issues that can be easily mitigated.

Concern 1: HTML and JSX Differ

The first common concern that I hear is that JSX differs from HTML. As I showed earlier, React uses an optional syntax that looks a lot like HTML called JSX. I say optional because JSX needs to be compiled down to plain JavaScript so that the browser can understand it. The code on the bottom is what is sent to the browser, so you're free to just use this syntax on the bottom if you prefer. But most people prefer using JSX since it feels extremely similar to HTML, and it's easier to read. Now JSX's syntax is 99% the same as HTML, but it does differ in a few ways, such as htmlFor instead of for and className instead of class. Inline styles are declared in JSON format. And finally, comments are handled in JavaScript style instead of HTML style. So as you can see, learning JSX's differences is trivial. The list of differences is quite short and thus easy to adopt. Now maybe you're still worried, but I have a lot of existing HTML. Won't that be a hassle to convert into JSX? Well the good news is, that's easy. There are multiple ways to handle it. Honestly, since there are only a few differences between HTML and JSX, I typically convert existing HTML with a simple find and replace. The list of differences is so small that it typically only takes me a moment. But there's also an online HTML to JSX compiler and an npm package called htmltojsx that you can use. With this online HTML to JSX compiler, you enter your HTML on the left, and it displays the resulting JSX on the right. As you can see, the two sides are quite similar, but I deliberately created an example on the left to show the core differences. Now if you have a lot of HTML to convert to JSX, you can convert it in bulk using the htmltojsx package on npm. This is a command line tool, and it uses the same code that's running behind the scenes on the online HTML to JSX compiler that I just showed you. So you can point this at a set of files and convert your HTML in bulk.

Concern 2: Build Step Required

The second common concern is closely related to the first. When you use JSX, React requires a build step. As I mentioned, you need to compile JSX down to plain JavaScript calls so that the browser can understand it. In practice, this is trivial to handle today. Frankly, worrying about needing a build step makes little sense today. These days, a build step is a critical part of just about any web application. No matter what JavaScript framework you're using, you're going to want to build step. You'll want to minify your code to save bandwidth. You'll want to transpile your code so that you can use modern JavaScript features today, even before your platform offers full support. And you'll want to lint your code and run your automated tests when you hit Save as well. So compiling JSX is just another thing that happens automatically along the way. Today's two most popular transpilers both work great with React, Babel and TypeScript, and both allow you to use modern JavaScript features today, even before all browsers offer full support. And, most importantly for React developers, both transpile React's JSX for you. And there are a variety of React boilerplates that make it easy to get started and have build steps built in automatically to transpile JSX for you. create‑react‑app, which I have mentioned earlier, is the most popular option today, and it also minifies and bundles your code and even includes automated testing support so you don't even need to configure your development or production build environment to work with JSX. This all just happens automatically.

Concern 3: Version Conflicts

The third concern is potential version conflicts. As I mentioned earlier, React with React DOM weighs only around 35K minified and gzipped. That's a very reasonable size, but there are some downsides to having a runtime at all. See, you can't run two versions of React at the same time on the same page, so this means that you need to keep your React components on the same version for a given page. In contrast, if you build standardized web components, you don't have to worry about version conflicts at all since there's no runtime. Standard web components just leverage the support that's built right into the browser. However, for reasons I outlined in a previous module, I still prefer working in React over using plain web components. And that's partially because the web component standard lacks features that I've grown to know and love from React and other frameworks, like efficient DOM updates, reactive data binding, and more. So, there are other interesting tools to consider, like skatejs, Svelte, and Stencil, which bring those features to web components without the need for a framework. These options are interesting because they leverage the web component standard, but add extra features. They also embed the runtime within each component, so you don't need to worry about version conflicts. And since React is a lean component library, you will often choose to use related libraries with React, such as React Router, so you need to run compatible versions. This means that you typically need to run a recent version of React to avoid a version conflict. In practice, though, I found version conflicts are rarely a problem in React. Since Facebook has been consistent about releasing code mods when breaking releases occur, upgrades to your existing React components can typically be easily automated. Here are three tips to avoid version conflicts. First, agree is a team which version of React you're working with. Second, upgrade React when you're upgrading related libraries. And finally, on the rare instances where there are breaking changes in a future release, decide as a team when to upgrade.

Concern 4: Outdated Resources Online

The fourth concern is old stuff showing up in searches. React is a large, mature community, and it has evolved since it was open sourced in 2013. Search for the term React example on Google, and you'll get over 300 million results. There are over 189,000 threads tagged with React on Stack Overflow and around 100,000 threads on related technologies like React, React Native, React Router, and Redux. And there are thousands of blog posts out there on blogging platforms like Medium and dev.to that cover React and related technologies. And hey, having many great resources online is a great thing, right? Absolutely. But there's an obvious risk. Some of this public content is outdated. React has evolved since it was released in 2013, so as you search around the web, you'll see some patterns that are no longer popular today. So what has changed? Well, recently, features have been extracted from React Core to keep the library lean and simple. Since React is used for more than just the web now, React DOM was extracted to a separate package, so you'll see many posts using the style on the left, but today reference the separate React DOM library for web development. And if you're doing development for other platforms, you'll import the renderer that's appropriate for that platform, such as React Native. Second, since most people are using ES classes today, React.createClass was extracted to a separate library called create‑react‑class. So you need to reference this separate library if you want to declare React components using the createClass style. And since only some teams choose to use PropTypes over alternatives like TypeScript and Flow, the prop‑types library was extracted to a separate npm package too, so you'll need to install the prop‑types library and import it like you see here on the right. Finally, mix‑ins were initially a popular way to share functionality between components in React. However, mix‑ins are no longer part of React Core. Today, React's Hooks are the most popular way to share logic across components. Of course, when in doubt, check React's documentation. It's excellent, up to date, and actively maintained by Facebook.

Concern 5: Decision Fatigue

The fifth and final concern is decision fatigue. React is lightweight and unopinionated, so there are multiple ways to do some of the same things. Okay, I'm about to run through a few decisions, but keep in mind one can view having many decisions as a glass half empty or a glass half full. I like having lots of options because it means that I can set things up in a way that's perfect for my team's unique needs and preferences, so I see React's rich ecosystem as a big win. Getting started in React can feel intimidating, so let me break this down for you. There's really five key decisions to make up front, your development environment, whether to use classes or functions, and how to handle types, state, and styling. Let's quickly walk through these five decisions. The first decision is a development environment. There are over 100 boilerplate projects available on GitHub, and Andrew Farmer was nice enough to create a searchable list of React boilerplates on his website. You can search through the list for things that you want and things that you don't. When starting React, this tool is a handy way to see all the different ways that you could choose to configure your team's React development approach. But I recommend starting with create‑react‑app, which is the official development environment that's supported by Facebook. This is a mature platform for rapidly creating react applications. This project includes automated testing, transpiling, bundling, linting, and an automated build process all set up and ready to go. And in a poll of over 2000 React developers, 65% use create‑react‑app. The next largest group of 25% chooses to build their own dev environment. I show how to build your own environment in my React and Redux course. And if you're wanting to build a native mobile app with React, I suggest using create‑react‑native‑app. Now, admittedly, create‑react‑app doesn't include all of your decisions baked in. For example, related libraries like React Router for routing or Redux for state management aren't included in create‑react‑app. But you don't need these to get started, so look into these related libraries later. On decision two, you need to decide whether to declare your components via classes or functions. Here's what the two approaches look like side by side. You can accomplish the same things in both, but today, most React developers prefer declaring React components as functions. The function syntax is more concise, and it tends to help avoid bugs. So for new development, I suggest using functions. That said, I show both class and function approaches in my React and Flux course and my React and Redux course. There are three popular ways to handle types: React PropTypes, TypeScript, and Flow. To see the difference between these options, let's consider a simple component called Greeting. With PropTypes, you can declare the types of the data that are passed into your component. Here, I'm declaring that the name passed into the Greeting component is a string. With PropTypes, types are checked only at runtime and only during development. TypeScript is the second option. It's a popular project from Microsoft. TypeScript is a superset of JavaScript that adds strong typing support and compiles down to plain JavaScript. TypeScript will feel very familiar it anyone who has coded in C# or Java. Here I'm using an interface to declare the type for the Greeting component's Props, and I'm saying the Props argument getting passed into my Greeting component has a type of Props. Unlike PropTypes, TypeScript checks types at compile time, so you find out earlier about any potential type issues. The third option is Flow, a project from Facebook for adding static type checking to your JavaScript. Flow provides type safety in a different way than TypeScript. With Flow, you add type annotations to plain JavaScript, and Flow intelligently infers types throughout your codebase. With Flow, you annotate the top of each file that you'd like it to check. Here, I'm declaring my type above the component, then specifying the type within the argument. Flow will process plain JavaScript without type annotations, and it will infer those types or, in other words, flow through your code. Now, Flow runs as a separate process, so types can be checked whenever you choose to run Flow. I recommend PropTypes for developers getting started with React. PropTypes are simple to implement, trivial to learn, and require no special configuration. But if you already know TypeScript, it's also a great option. Create‑react‑app has TypeScript support built in, so it's easy to get started. And as you can see in this Twitter poll, Typescript is quite popular in the React community today. React works great alone, but many developers prefer to enhance React with popular third‑party state libraries. Now what do I mean by state? Well, simple. The state is your app's data. Popular ways to handle state in React include plain React, Flux, Redux, and MobX. React handles state great all by itself, so these other libraries are totally optional. With plain React, your components handle state on their own. But shortly after React was open-sourced, Facebook also released Flux as an optional way to handle state in React. Flux is still heavily used by Facebook, and it centralizes your application's state. But today, Redux is the most popular state management library for working in React. Like Flux, with Redux, your app's data is centralized, but Redux offers a more elegant approach than Flux and uses an immutable data store. Finally, MobX is a lighter weight alternative to Redux, but with a fundamentally different take on state management. MobX uses observable data structures. In short, Redux is more explicit and scalable, but MobX requires less code and is easier to learn. That said, I want to emphasize React works great all alone. You can build applications using just plain React. You often don't need a separate state management library like Redux. I recommend starting with plain React. Don't feel obligated to immediately learn and use Redux or MobX. You can build powerful apps using just React by itself. And this final decision is where it gets a little silly. There are over 50 different styling approaches that you could potentially use with React, but really, React works great with traditional CSS, Sass, and Less too, so my suggestion is just get started by using whatever you know today. And in fact, the majority of React developers continue to use traditional styling approaches with React. After you've gotten comfortable with React, if you're curious about the styling options, I explore them in detail in my Creating Reusable React Components course. So in summary, yes, the benefit of React being a lightweight library is that you have options, but the obvious downside is the number of options can feel intimidating, so I'd encourage you to use these recommendations as a starting point for standardizing your approach. And don't let these decisions intimidate you. The implications of these decisions are really mostly minor anyway. Okay, let me wrap up the course by suggesting some next steps.