Ejiro Asiuwhu Frontend Engineer with rock-solid experience in building complex interactive applications with JavaScript, TypeScript Vue.js, NuxtJS, React, Next.js, and other tools in the JavaScript ecosystem. Decomposing complex problems into logic, data, and UI components are my forte, and despite JavaScript frameworks, I build products that scale well 🚀. I author meaningful technical content, regularly ✍🏽.

Blazor vs. React

10 min read 2828

Blazor and React Logos

There are several frameworks to choose from when building Single Page Applications (SPAs).

The 3 most popular are React, Vue, and Angular. To build SPAs with these three frameworks, JavaScript is required.

What happens when a developer is interested in building for the SPAs but doesn’t want to deal with the weirdness of JavaScript? Let’s find out.

Here comes Blazor

Blazor is a new Microsoft UI framework that uses a unique approach for leveraging C# .NET and the WebAssembly framework to create SPAs running in web browsers. It essentially allows a developer to build rich and interactive client-side applications with HTML, CSS, and C#.

On the other hand, we have React: a declarative, efficient, and flexible JavaScript library for building user interfaces and UI components.

React and Blazor share the similarity of being client-side frameworks/libraries for building rich and interactive modern client-side applications.

One thing that’s unique about Blazor is its JavaScript interoperability. This means a Blazor app can invoke JavaScript functions from .NET methods and .NET methods from JavaScript functions.

Blazor is made up of two major projects: Blazor WebAssembly (the client-side) and Blazor Server (the server-side). In this article, our focus will be comparing Blazor WebAssembly with React.

Before we dive deeper into things, let’s answer one pressing question.

C# running in the browser?

The big question here is, how does C# run in web browser? The technology that makes this possible is called WebAssembly, an open standard supported directly by current browsers on desktop and mobile platforms. You get to write C# code instead of regular JavaScript or React, and the compiled code runs natively in modern web browsers.

Getting started

In this article, we’ll explore how React and Blazor differ in the following areas:

We made a custom demo for .
No really. Click here to check it out.

  • Folder structure
  • Programming language
  • Templating
  • Performance
  • Ecosystem
  • Package manager
  • Communication between components
  • Routing
  • Dealing with HTTP

Folder structure

Let’s create a Blazor app and a React app and make a head-to-head comparison with what we get right out of the box.

To create a new Blazor project, you need to download and install the .NET SDK and run the following command on your terminal:

dotnet new blazorwasm -n BlazorApp

The new blazorwasm command means we are creating a new Blazor project with WebAssembly, and the -n flag is for the name of project:

The Blazor Webassembly Folder Structure

The Programs.cs File

The program.cs file contains the main methods needed to get our WebAssembly app up and running.

We’re also mounting our app and selecting a tag with an id of “app”. Also, the HTTP client is loaded using a dependency injection technique.

The HTTP modules in our Blazor app are built on top of the JavaScript Fetch API.


Creating the React App Folder Structure

index.js in a React.js app is similar to program.cs in a Blazor app. Here, the React DOM renders our app component, and the element with the id of “root” is selected as our root component:

Index.js in React App

Programming language

Blazor uses C# as its programming language instead of JavaScript and leverages the existing .NET ecosystem of .NET libraries. This is definitely a plus for the C# guys, as they get to expand their skill from just being able to write backend code with C# to the point where they can now build fullstack web and mobile applications with C# as the programming language.

The downside to this is that C# may look and feel unnatural to JavaScript developers. But once you get a good grasp of C#, you can build powerful fullstack application written entirely in C#.

React, on the other hand, uses JavaScript as its programming language. So essentially, web developers still get to write the language they’ve gotten most used to. And with React Native, you can build web, Android, and iOS applications that share the same code snippets.

Templating

When creating an SPA with React, the Create React App Toolchain is recommended. This will, by default, initialize a React App configured with JSX, which is a syntax extension for JavaScript. It acts like a templating engine that allows you to write HTML in React and also write JavaScript in HTML.

JSX in a React App

Blazor uses the Razor template engine, which has been around for years. The templating engine is not new in the C# and ASP.NET ecosystem. It’s used to embed server-side code into web pages using C# and ASP.Net.

The Razor Template Engine in a Blazor App

Just like JSX, Razor template engine allows you to write C# code in your markup

Performance

Blazor projects are slow on the client-side because you have to download the entire dot net runtime along with the necessary DLL libraries on your browser.

Blazor apps have latency issues. So if you’re building a web application that’s going to be accessed by people across the globe, Blazor is not your go-to framework.

One other important thing to note is that during development in a Blazor app, you don’t get to enjoy hot-reload features that you have in React. As a result, your development process is likely going to be slow because you have to hit the restart button to get your app to restart.

Lighthouse Score

Blazor App Lighthouse Score

The lighthouse score from the diagram above clearly shows that Blazor apps have a serious performance issue. The initial page load time is slow, since the necessary dependencies have to be downloaded on initial page load.

React App Lighthouse Score

This is where React shines. Since it’s a UI library, the core React package is as lean as lean could be. It is fully optimized out of the box to build blazing-fast modern client-side applications using a component-based paradigm.

Ecosystem

At the time of writing this article, five new editions of Blazor have been announced by Microsoft, including Blazor WebAssembly and Blazor server.

On the other hand, the React ecosystem is extremely large to the point that you will find packages on npm for almost everything you’re trying to implement.

React is fully backed by Facebook, and it has a lot of community support given the fact that it changed a whole lot about how client-side applications are built. Also, it feels natural to a web developer because it is still JavaScript.

React has a selling point of “learn once, write anywhere.” Essentially, with React, ReactDOM, and React Native, you can build out highly interactive and rich frontend web, Android, and iOS native applications.

This makes it easy for most companies to build out solid products and platforms at a relatively low cost, because they’ll just hire a developer who’s good with React.js and React Native.

GitHub Rating

At the time of writing this article, React has over 160k stars on GitHub. It’s inarguably one of the most loved JavaScript Framework in general.

React Stars on GitHub

Meanwhile, Blazor has about 9.3k+ stars on GitHub.

Blazor Stars on GitHub

Given the fact that Blazor was initially released in 2018 and it’s relatively new to the developer community, this may not be a valid reason to mark it down

Blazor PWA vs PWA Support in React

When released, the Blazor PWA will provide support for developer to build high-end Progressive Web Apps. In a React.js application, adding PWA support is a breeze.

Running the following command will initialize a React app with a service worker file added:

npx create-react-app my-app --template cra-template-pwa

Blazor Native (experimental), Blazor Hybrid vs React Native

Blazor Native essentially allows developers to build native mobile apps with Blazor using the Mobile Blazor Bindings. Using C# and .Net, Android and iOS app development with Blazor is actually a possibility.

Blazor Hybrid apps are a combination of native and web UI in a single app. This means you can write the native UI for your app using Blazor, and also create a web UI in your app with Blazor.

This creates the possibility of using Blazor to build both your web and mobile applications.

Essentially, you are going to share code snippets across your web and mobile application. This is definitely a good time to be a C# .Net developer.

The React way of building native mobile applications is React Native. It enables React developers to build mobile apps with React. With it, you can use native UI controls and have full access to the native platform.

React Native is stable and it’s being used in production today, but Blazor Native is still in the experimental phase of its development. It has little community support when compared to React Native.

Package manager

React, like other JavaScript frameworks and libraries, uses npm and yarn as package managers for you to manage dependencies (external code written by you or someone else) that your project needs to work correctly.

In a Blazor WebAssembly app, a package can easily be installed in one of the following ways:

  • PackageReference
  • .NET CLI
  • Package manage
  • Paket CLI

To install a package with PackageReference, navigate to the Blazorize.csproj file and add the package inside of the ItemGroup tag:

<PackageReference Include="System.Net.Http.Json" Version="5.0.0" />

To install a package with .NET CLI, navigate to the root of your app directory in your terminal and run the following command accordingly:

dotnet add package Microsoft.AspNetCore.Blazor.HttpClient --version 3.2.0-preview3.20168.3

To learn about the .NET CLI and Paket CLI, check out this guide and this guide, respectively.

Note: Here we are installing the Blazor HttpClient package.

Communication between components

The React way

React gives us two main approaches by default for handling state in your components.

A component can either handle its own state or data, or they can accept data via props.

In dealing with the HTTP section, we’ll see how a component handles its own state.

Here’s how a component accepts data via props from its parent component in a React app:

// Parent Component

export default function Blog() {
    const blogPosts = [
        {
            id: 1,
            title: 'This is the title',
            content: 'This is some random content',
        },
        {
            id: 2,
            title: 'This is the title',
            content: 'This is some random content',
        },
        {
            id: 3,
            title: 'This is the title',
            content: 'This is some random content',
        },
        {
            id: 4,
            title: 'This is the title',
            content: 'This is some random content',
        },
    ]
    return (
        <>
            <BlogCard blogPosts={blogPosts}/>
        </>
    )
}

Here, we passed in blogPosts, which is an array of objects containing blog posts, to the BlogCard component (child component):

// Child Component

export default function BlogCard( { blogPosts } ) {
    return (
        <>
            {blogPosts.map(blogPost => (
                <div className="blog-post" key={blogPost.id}>
                    <h1>{blogPost.title}</h1>
                    <p>{blogPost.content}</p>
                </div>
                ))}
        </>
    )
}

Now, when we render the child component BlogCard, we can pass in the list of blog posts via props.

To learn more about props in React, check out the official docs.

The Blazor way

In Blazor, a child component can receive data from its parent components via parameters.

// Child Component
<h2>@Title</h2>
<p>@Content</p>
@code {    
   // Demonstrates how a parent component can supply parameters
    [Parameter]
    public string Title { get; set; }
    [Parameter]
    public string Content { get; set; }
}

When you render a BlogCard component, you can pass in a Title and Content and it will be rendered accordingly:

<BlogCard Title="What is Blazor?" Content="Blazor is a web UI framework using C#/Razor and HTML..." />

Routing

In a React.js application, the router does not come preconfigured or installed. The React Router package is mostly used to implement client-side navigation.

According to the documentation, React Router works anywhere React is rendered, including in React Native projects. The API is really simple, yet it handles a lot of powerful features like URL parameters, component redirects, lazy loading, page transitions, nested routing, and more.

To set up routing in a React.js app, typically you would install the react-router-dom package and wrap your entire app in the index.js file with the browser router module from the React Router DOM package. Then, in your App.js component, you would render your pages with the route module from the React Router DOM.

Here are some images to illustrate how routing works in React.js:

Routing in React.js

Routing Path

In a Blazor WebAssembly (client-side) application, the routing system leans on ASP.NET’s existing routing engine. You can map a route to a Blazor component by using the @page directive and then the path that you want to link to at the top of your file.

Bam! It’s as simple as that. To navigate to another page, you have to make use of the NavLink component. This is similar to how the NavLink component works in the react-router-dom.

Routing in Blazor

Programmatically navigate between pages in a Blazor app by injecting the NavigationManager at the top of the file with this code:

@inject NavigationManager NavManager

Then, call the NavigateTo method in a function on the NavManager you’ve injected:

@inject NavigationManager NavManager
<p>Learn more about us</p>
<button @onclick="navigateHome">Go back home</button>

@code {
    private void navigateHome()
    {
        NavManager.NavigateTo("");
    }
}

Dealing with HTTP

Blazor

To explain how to handle HTTP requests in a Blazor application, we will create a FetchPost.razor file in the pages directory:

@page "/http"
@inject HttpClient Http

<h1>Blog post</h1>

@if (posts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Title</th>
                <th>Body</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var post in posts)
            {
                <tr>
                    <td>@post.title</td>
                    <td>@post.body</td>
                </tr>
            }
        </tbody>
    </table>
}
@code {
    private BlogPost[] posts;
    protected override async Task OnInitializedAsync()
    {
        posts = await Http.GetJsonAsync<BlogPost[]>("https://jsonplaceholder.typicode.com/posts");
        Console.WriteLine(posts);
    }
    public class BlogPost
    {
        public int id { get; set; }
        public String title { get; set; }
        public String body { get; set; }
    }
}

There are three interesting things that are going on here.

First, we’re injecting HttpClient. This is a service that helps us make HTTP calls using the HTTP client.

Note: As of Blazor version 3.1.0, you need to add Blazor HTTP Client to your Blazorize.csproj file.

Then, we’re invoking HttpClient using the method GetJsonAsync() to fetch a JSON from the defined endpoint.

Finally, we’re creating a result type with the type BlogPost that, based on the incoming JSON structure, is able to pick out the relevant data found on the property post.

Injecting HttpClient

This is done at the top of the page with this code: @inject HttpClient Http

Invoking HttpClient

Here we are actively fetching the data. We do so by defining a life cycle method, OnInitializedAsync(), that is guaranteed to run when the page is initialized.

React

One of the benefits of using a library like React is the flexibility of its tools. React doesn’t provide an http client like Blazor, so a React developer can decide to make http requests using the Fetch API, Axios, or even XHR.

We are going to make use of the JavaScript Fetch API for http requests.

Here is how to make a simple http request in a React app using the built-in JavaScript Fetch API:

// post.js

import React, { useState, useEffect } from 'react'
export default function Post() {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/posts")
            .then(response => response.json())
            .then(post=> {
                setPosts(post)
                setLoading(false)
            })
    }, [])

   return (
        <div>
            {
            loading ?
                (
                    <p>Loading...</p>
                ) : (
                    posts.map((post, i) => (
                        <div>
                            <p>{post.title}</p>
                            <p>{post.body}</p>
                        </div>
                    ))
                )
            }
        </div>
    )
}

Notice that we are calling the endpoint on the useEffect Hook. This tells React that our component needs to fetch the data from our API after render, and then when our request is successful, we need to call setPosts and pass our post objects from the API.

For more details on how useState Hooks work in React, check out the official docs.

For a more detailed guide on the http request in a React App, check this out.

Conclusion

Choosing a frontend framework for building an SPA depends on a lot of factors, including team preference, ecosystem, performance, and scalability.

In this article, we have compared React and Blazor side-by-side to see how both of these awesome frameworks work.

React and Blazor are similar in a few ways, and they can be used to accomplish the same tasks. So which one should you choose to work with? You might have to consider their popularity, the type of project you’re building, scalability, and maintainability.

From the above general perspectives, you should be able to make informed decisions when choosing a front-end framework for your next project.

Let me know in the comments section below what you thought of this article. I am social on Twitter and GitHub. Thank you for reading, and stay tuned.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Ejiro Asiuwhu Frontend Engineer with rock-solid experience in building complex interactive applications with JavaScript, TypeScript Vue.js, NuxtJS, React, Next.js, and other tools in the JavaScript ecosystem. Decomposing complex problems into logic, data, and UI components are my forte, and despite JavaScript frameworks, I build products that scale well 🚀. I author meaningful technical content, regularly ✍🏽.

15 Replies to “Blazor vs. React”

  1. Huge mistake there in performance, blazor in this case compiles to web assembly, so is not true that the client needs to download the entire. Net ecosystem plus the dll. Misleading and untrue.

  2. I have an incredible amount of bias, but I absolutely love how elegant Blazor is. The implementation of components with getters and setters? Fantastic telegraphing. Binding is just dead simple. Building a modern front end framework off of such a strong base like ASP.NEat just makes a ton of sense.

  3. A tad biased towards React my friend and get your facts right before trying to play down the benefits and performance of Blazor… It is the future…

  4. I’m a React and Blazor developer but I prefer Blazor because I can integrate FE and BE using only one enviroment and language.

  5. Mono runtime and app dll’s are downloaded “once” in Blazor wasm. From then on, the only interaction with the server is for fetching json data for binding to UI. Blazor is literally blazing fast after the initial app download. With the upcoming AOT changes in .Net 6, Blazor will be much more faster and efficient even in initial download size and performance.

  6. Blazor is definitely the future. It’s crazy how quickly it has been able to get to the point where it’s comparable to the major JavaScript frameworks that have been at this for so long. I was very apprehensive at the start of going the Blazor route, but after using it, I never want to look back.

  7. You’re comparing apples to oranges here. React is a library, and Blazor is a framework. For example, React can be used standalone by just loading a script from a CDN. This article does a disservice to both technologies.

  8. I see a lot of enthusiastic comments below each of Blazor article but not agree. I worked with Blazor not so much but after one MVP I can say that I don’t like Blazor. Maybe some days it will be ready to touch my hart, but not today:

    1. Blazor is slow. Maybe it is only for me, but I can see a little lag after each click;
    2. has almost no 3rd party libraries. You need to create your own UI-components or choose between just a couple of UI-libraries (half of them are paid). And these UI-libraries often ugly and have bugs even on demo pages;
    3. “You can use one language for front and back” (of only we had Node.js). Yes, but no. You still need to know JS, because WebAssembly has no access to browser API’s by design. You can not work with canvas directly, as an example. Also scrolls, querySelectors, elements positions and so on;
    4. using JS-libraries is complicated. You need to download source codes and put them into `wwwroot` folder, then add js- and css-files into your `index.html` (you can use webpack for this, but you have to do it yourself, Blazor doesn’t have this functionality out of the box);
    5. no LESS/SASS, you also need webpack (not sure how to do it for css-isolation).

    Maybe some of these issues have been fixed in fresh releases.

  9. The “Stars” is for the old Blazor repo, Blazor is part of ASP.NET Core and is therefore maintained with the rest of ASP.NET Core https://github.com/dotnet/aspnetcore. I think this changed over a year ago with the first release.

    @Ivan, LESS/SASS is supported using a preprocessor, its the same as normal css isolation in blazor, you’d do something like Page.razor.less which would be compiled into Page.razor.css before the build and would then get packed as you’d expect a plain isolated css file. Blazor can use any JS based UI elements, so yes although there isn’t that many Blazor native packs, it’s not hard to use JS based ones where you logic is still within the C# side. Blazor is still a bit slow, but most of the slowness is due to incorrect writing of the page, it’s still in its infancy perf wise and has a long way to go to catch up to javascript based frameworks. I find it responsive enough so long as you don’t use asynchronous JS interop and make sure you use the virtualizer feature for long lists.

  10. Interesting that no one’s given Server-side Blazor consideration (which is what I’m using). The first-page initial download is rediculously small (because it’s all on the server!), and once that SignalR hub has your front-end wired up to the back-end server via a WebSocket connection – the interaction is pretty fast. I’ve even done terrible things like have a timer on the server firing UI changes down to the browser 30 times a second (like JQuery animation used to) – and it responds well! (no, this is not production code.)

    One major advantage Server-side Blazor has is access to data. Your code is probably already running in Azure / AWS, and you’re a lot closer to the data than your client-side cousins, so if you take the hit of not trying to hide behind an IHTTP interface of some kind, you can crack open the Entity Framework, and grab that data! No translation to JSON objects necessary. So in this way, you may actually asynchronously perform updates to the UI (a little) faster than you could with front-end code relaying information via a Service’s API. We also get the benefit of having web-events poking your back-end to inform it of database changes, which can then be pushed down to the front end. In server-side Blazor, that kind of thinking seems a little easier to implement as a result of the underlying SignalR connection. Also, your code feels more like a part of the server, and that logical separation of concerns, which shifts the way you think about the code.

    I don’t think at this point there’s any getting around the fact that some JQuery knowledge is still required. But seriously, that’s bare-bones thinking. Despite this fact, at least 99% ouir development hasn’t needed any javascript interaction, except via 3rd party UI components. Who on the javascript side doesn’t use a 3rd party library like Bootstrap for UI components, and css magic? The same is true for Blazor. You’re likely to accomplish most of your work with 3rd party libraries (there are both commercial and open-source options) so complex ui components and areas we just can’t touch (such as Canvas, as previously mentioned) are now well within our grasp with C# interactions.
    Isn’t there always a library out there tryingf to solve all your problems? The only problem now, is finding it (NuGet) and using it!!

  11. 1) Blazor Wasm is only slow for the initial app download after that it blazingly fast. However MS continues to improve this, it is after all a new framework.

    2) For most of the points you raise there I would say just checkout awesome Blazor https://github.com/AdrienTorris/awesome-blazor

    There are plenty of UI components for Blazor, you do not need to create your own UI-Components, dismissing them as ugly is a matter of opinion.

    3. Yes you can use C# for both front end and back end. The fact that you can use JavaScript for both front end and back does not take away from the fact that you can use C# in a similar way. That simply means you have a choice. You can work with the canvas using a Blazor canvas extension and Blazor gives you reference to HTML elements via @ref and ElementReference, so you can deal with element positions and so on.

    4. There is nothing complicated about using JS libraries, many can be installed automatically via NuGet, and Blazor/C# wrappers already exists for many popular ones such as for chartJs, ironically Canvas etc. There may be need to setup up some js interop but that is usually a matter of copy and paste. How hard is it to add JS and CSS refences to an index.html file? Is there any website that does not use them?

    Yes Blazor is new but it is remarkable how well it already stacks up to JS frameworks. One should not approach it with the same mindset of using JS. I know JS but for the Blazor production apps I have already completed I have hardly ever needed to write any lines of JS beyond to setup some interOp with a third party JS library. However a lot of JS libraries I have need have an equivalent C# implementation or a wrapper already from the days of asp.net MVC and webforms. This point of knowing JS is exaggerated, Blazor was designed for C# developers to write SPA application with very little need if at all to know JS.

  12. Blazor apps have latency issues. So if you’re building a web application that’s going to be accessed by people across the globe, Blazor is not your go-to framework.

    If it’s WASM then once the initial package is downloaded to the client there are no other calls needed other than network calls like fetching data from a database. The app essentially functions like an old school Windows Forms app.

Leave a Reply