Getting started with React Native for Windows
Published Oct 14 2019 11:15 AM 58.6K Views
Microsoft

If you're familiar with web development, you'll know for sure React. This framework, built by Facebook, is becoming more and more popular to build client-side web experiences. Unlike other frameworks like Vue.js or Angular, React focuses only on the View component of a web application. It isn't a fully fledged framework like jQuery or Angular, which have an opinion on everything and, as such, they provide lot of features to perform all the kind of tasks, from HTML templates to APIs to handle HTTP requests. You need to rely on plain old JavaScript (or TypeScript, if you prefer) or on 3rd party libraries to achieve these goals.

 

What makes React peculiar (and not so easy to understand at the beginning if you're coming from traditional client-side development for Windows, like me) is the different development approach. You may be used to patterns like MVC or MVVM, which goal is to separate the UI from the business logic so that you can make your application easier to test, maintain and evolve. React, instead, being focused only on the View, is based on the concept of components, which are the different pieces that compose a page. Every component is independent from the other and it includes both the UI and the logic to handle the various events that it can trigger.

 

Since code is easier to understand than words, here is how a typical React component looks like:

 

class App extends React.Component {

  constructor(props) {
    super(props);
    this.showAlert = this.showAlert.bind(this);
  }

  componentDidMount() {
    window.alert("The component is ready!");
  }
  
  showAlert() {
    window.alert("Hello world!");
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <button onClick={this.showAlert}>Click me!</button>
        </header>
      </div>
      );
  }
}

As you can see, the component defines both the UI and the logic to handle the events associated with it:

  • The render() function is the one which declares the UI that this component will display.
  • The showAlert() function is triggered when the user clicks on the button declared in the UI.
  • The componentDidMount() function is part of the component's lifecycle and it's triggered when the component has been rendered and it's ready to work.

The UI might look like HTML, but it's actually defined using a special language called JSX, which is based on XML and it allows to declare your UI with JavaScript. It may sound blasphemous, but the goal is to go past the standard templating approach used by other frameworks, which is good when you just want to display some data, but it has its limitations when you want to do something more complex, like displaying or hiding something based on a specific condition. In the previous code you can see an example of this approach. In jQuery or another similar framework, you would need to use an API to get a reference to the button and then hook up the event. In React, instead, we can declare it just inline, by subscribing to the onClick event and by specifying the name of the function to invoke inside curly brackets.

 

<div> and <button> may look like plain HTML tags, but they're actually not. You can notice it, for example, by the usage of two attributes, className and onClick, which don't exist in standard HTML. React will take care of translating these JSX controls into the corresponding HTML ones and to handle the various state changes. To make thing simpler, the JSX controls in React resembles as much as possible the HTML ones, so the syntax will be very familiar to you.

 

Due to the growing popularity of React, Facebook has decided to extend the framework to support mobile development with the introduction of React Native. This was made possible by the fact that one of the core features offered by React is abstraction. React itself doesn't offer too many built-in features which are tight to a specific platform, but it leverages a render target to make sure that the View is rendered in the proper way. In the previous examples, React used a render target that can turn JSX into plain HTML. As such, React Native in nothing more than React with a different render target, which turns JSX into mobile controls.

 

React Native, from a mobile development experience point of view, can be seen as a mix between the classic Xamarin approach and the Xamarin Forms one. Like Xamarin Forms, it shares the opportunity of building truly native applications. React Native, in fact, doesn't use a WebView to render the HTML and JavaScript, like other web based technologies like Cordova. The various JSX controls are rendered using the corresponding native controls for Android or iOS, making the UI and the user experience coherent with the rest of the operating system. Xamarin Forms does the same, but by leveraging XAML as a markup language. However, like classic Xamarin, the goal of React Native isn't really to write an application once and run it everywhere, but rather allowing a team to build mobile applications using the same knowledge and sharing the same libraries. You will find out, in fact, that React Native includes many controls which are cross-platform (like Text or Image), but also many others which are specific for Android and iOS and that can't be used in a cross-platform way.

 

React Native includes a render target for iOS and Android but, since BUILD 2018, Microsoft has started to work on a render target for Windows. At BUILD 2019, however, Microsoft has announced a rewrite of the framework from C# to C++, with the goal to get better performances and to be better aligned with the core react-native implementation, which is built in C++ as well. The technology behind this framework is the Universal Windows Platform. React Native for Windows creates a new UWP project and the various JSX controls are rendered using native controls from the Universal Windows Platform and, in the future, from the WinUI library.

 

The framework is really flexible and it opens up many opportunities for Windows developers:

  1. You can build UWP applications from scratch using only React Native.
  2. You can integrate React Native components inside native UWP applications, allowing you to mix UWP controls with React Native controls.
  3. You can integrate React Native components inside WPF or Windows Forms applications, by leveraging XAML Islands, the technology which allows to render UWP controls inside Win32 applications.

In this blog post we're going to explore all these options. However, the purpose of this post isn't to be a comprehensive overview of React Native. I will give for granted that you're already familiar with this technology. If it's not your case and you want to learn more, you will find lot of tutorials and documentation on the official website. You can also start from the React website. The main concepts, in fact, are exactly the same between the two platforms, with the only difference that React outputs HTML, while React Native native controls.

 

Getting started

Let's start by setting up our computer with all the requirements needed to build React Native applications for Windows. The first one is Visual Studio 2019 with the following workloads installed:

  • Universal Windows Platform development (make sure to enable the C++ (v142) Universal Windows Platform tools option)
  • Desktop development with C++

Make sure also to check, in the Indivual components section, the following ones under Compilers, build tools and runtimes:

  • MSVC v141 - VS 2017 C++ x64/x86 build tools (v14.16)
  • MSVC v141 - VS 2017 C++ ARM build tools (v14.16)

Now let's move to the "web tools". The first one is NodeJS, the JavaScript runtime built on top of the Chrome JavaScript engine. Everything around React Native (the core, libraries, etc.) is distributed as packages through the popular NPM package manager, so you'll need the NodeJS runtime to leverage it. You can get it from the official website.

 

Optionally (but highly suggested) is to install Yarn, a package manager for Node. As we're going to see in the next steps, it will help us a lot in setting up the whole environment. You can download it from the official website.

 

Last but not the least, if you want to debug your application you will need to leverage the Developer Tools included in Chromium. The official guidance on GitHub specifically invites you to install Chrome, but also the new Edge based on Chromium works like a charm.

 

That's it! Now we can start to create our first React Native project. You can refer to the guidance provided on the GitHub repository. I won't repeat them here since the steps might change in the future (for example, the targeted React Native version has changed multiple times since the project started).

The last tool I'm going to mention isn't exactly a requirement, but a strong suggestion. In order to build your React Native application you will need to use an IDE. Sure, you can use also Notepad, but there are better options out there, like Visual Studio Code, which offers also an extension for React Native which gives you IntelliSense, debugging, etc.

 

Make sure to have plenty of space on your hard disk. Since the React Native implementation for Windows is based on C++, the compilation artifacts will be quite big, so an average project's folder can easily reach the size of 5-6 GB.

Running your React Native for Windows project

The easiest way to launch your React Native for Windows project is to run the following command from your project's folder:

 

react-native run-windows

In the past there have been some issues that prevented this command to work properly. Most of them should be fixed now but, in case you're still hitting one of them, here is an alternative procedure:

  1. Open in File Explorer the windows folder inside the folder which contains your React Native project.

  2. Open the Visual Studio solution you'll find there. The name of the solution will match the name of the project.

  3. The solution is made by different projects, all based on C++. The main one (which contains the actual application to deploy) is the one which name matches with the React Native project's name. In our case, it's TodosFeed.

    ReactNativeSolution.png

  4. Compile the whole solution (again, it will take a while because of the C++ projects), then right click on the UWP project and choose Deploy. Make sure that, in the configuration dropdown, you choose an architecture which is suitable for your computer, like x86 or x64. The default value, in fact, will be ARM.

You should always launch the UWP project either from the Start menu or by pressing CTRL-F5 in Visual Studio, without attaching the debugger. The reason is that, in this scenario, the UWP app is just the "host" of the React Native application, so the real debugging must be done on the React code.

Before launching the application, however, you have to manually run the React packager by typing the following command in the project's folder:

 

yarn start

What is the React packager? It takes care of a few important tasks, like translating JSX into code that the target platform will understand and combining all your JavaScript into a single file. When you're in development mode, the command prompt with the React packager must always be up & running. This way, every time you make a change to the code of your React Native application, the packager will automatically create a new bundle and refresh the application.

 

Packager.png

 

Once the packager is ready, it should automatically launch Chrome on the local server which is used to serve the React application. If it doesn't happen, you can open it manually (or you can launch Edge based on Chromium) and open the URL http://localhost:8081/debugger-ui/. Then you can press F12 or CTRL-SHIFT-J to turn on the developer tools, which will help you to see any error that might arise in the React Native application. This operation is very important because, if the local development server isn't up & running, the UWP application won't be able to render the React Native content and you will get an error like the following one:

 

InstanceFailedToStart.png

 

Now that both the packager and the development server are up & running, you can launch the UWP application you have deployed. If you did everything well, you will see the packager starting to serve the various files in the command prompt and, in the UWP application, you will see the default React Native starter template.

 

ReactNativeTemplate.png

 

Using React Native to build a full UWP application

This is the simplest task, since with all the steps we have taken so far we have already created a full UWP application based on React Native. Let's try to create a more realistic one compared to the default template, which we're going to reuse for the next scenarios. As already mentioned, the UWP app is just the host of the React Native one, so to start actually coding you need to open the React Native project's folder with Visual Studio Code. Just right click on the folder and choose Open with Visual Studio Code or, alternatively, if you're still in the command prompt, type:

 

code .

As mentioned, the default page you see in the application is defined in the App.js file. Let's replace the default content with a simple application that displays a list of to-dos, downloaded from a REST service. This will be the final look & feel:

 

TodosApp.png

 

Nothing too complex, but enough to play with the React Native and Windows capabilities.

Let's start by building a component that will display the list of to-dos. Create a new folder in the project called components and, inside it, create a file called TodosList.js.

First, let's import the required controls:

 

import React, { Component } from 'react';
import {
  ActivityIndicator,
  View,
  FlatList,
  Text
} from 'react-native';

We're going to use four controls from React Native:

  • ActivityIndicator, to display a loading icon when the data is being downloaded from the REST service.
  • View, which is the basic container of React Native. Typically, it's the main entry point which contains, as child, the other controls. Think of it like the Page control in XAML.
  • FlatList to display the list of to-dos we have downloaded.
  • Text, to display a text.

Let's start to define our component:

 

import React, { Component } from 'react';
import {
  ActivityIndicator,
  View,
  FlatList
} from 'react-native';

class TodosList extends Component {

  render() {
    return(
      <View>
        <ActivityIndicator size="large" />
        <FlatList /> 
      </View>
    );
  }
}

export default TodosList

This is the basic skeleton, since the component doesn't actually include any data or any action. The component is defined using the standard React Native syntax based on ES6, the latest definition of the JavaScript language. We create a new class which extends the Component one, which is provided by the React library. The component defines a render() method, which include the JSX that represents the UI. The current View contains an ActivityIndicator and a FlatList which, however, we need to populate with some data.

Let's enhance our component with some new code:

 

import React, { Component } from 'react';
import {
  ActivityIndicator,
  View,
  FlatList
} from 'react-native';

class TodosList extends Component {
  constructor(props) {
    super(props);
    this.state = { todos: [], loading: false};
  }

  async componentDidMount() {
    this.setState( { loading: true});
    var result = await fetch("https://jsonplaceholder.typicode.com/todos");
    var json = await result.json();
    
    this.setState( { todos: json.slice(1,20), loading: false});
  }

  render() {
    return(
      <View>
        <ActivityIndicator size="large" animating={this.state.loading} />
        <FlatList data={this.state.todos}
                  renderItem={({item}) => <Text id={item.id}>{item.title}</Text>} /> 
      </View>
    );
  }
}

export default TodosList

First we need to introduce one of the most important concepts in React, state. It's a key - value pair collection where we can store data that must be displayed by the user interface. The nice bonus of the state management in React is that it automatically keeps the UI in sync. Whenever you're going to change one of the values stored in the state, every UI component connected to that value will be automatically updated. If you're a XAML developer, this concept should be familiar to you since it's similar to binding.

 

We define the state in the constructor of the component and we setup two properties: one called todos, which is an array that will store our collection of to-dos; the other one is called loading and it's a boolean we're going to use to hide / display the loading indicator.

Now that we have a place where to store our to-dos, we need to download them when the component is rendered. To achieve this goal we leverage the componentDidMount() method, which is one of the many available functions to handle the lifecycle of a component. Inside the function we use the JavaScript fetch API to download the list of to-dos from a REST service. We're using https://jsonplaceholder.typicode.com as endpoint, which is a service that returns fake data for testing and development purposes. The fetch API is asynchronous, so we use the async / await approach (supported by all the modern browsers nowadays) to handle it. In the end we convert the response into a JSON object by calling another asynchronous method, json(), and we store the result inside the todos object in the state. We also change the value of the loading property, so that we can hide the loading indicator.

 

You can notice two things:

  • To set the state, we are using the setState() method instead of setting it directly. This is required to enable the sync, otherwise the UI won't be notified that the value of one of the properties has changed.
  • We use the slice() method to take only the first 20 items from the result.

Now that we have some real data inside the state, we can populate the UI controls we have previously created:

  • We connect the animating property of the ActivityIndicator control to the loading property stored in the state (this.state.loading). This way, the loading indicator will be displayed when we start the operation and hidden when the data from the REST service has been downloaded.

  • We connect the data property of the FlatList control to the todos property stored in the state (this.state.todos). This way, the list will be automatically populated with all the items that have been downloaded from the REST service.

  • We use the renderItem property of the FlatList control to define how every single item of the list should be rendered. We express this property using a lambda expression, which gives us a reference to a single to-do in the list. For the moment we use a simple Text control and, inside it, we display the value of the text property of the to-do. We can understand where this property is coming from by opening the URL of the REST API in a browser or in a tool like Postman. We will see that each item inside the collection has the following properties:

    • userId
    • id
    • title
    • completed

As such, from the item object we can directly access to each of them.

 

Now that we have defined the TodosList component, we need to display it in replacement of the original React Native template. Move to the App.js file and, inside the class which defines the main component, change the render() method to:

 

class TodosFeed extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>To-dos</Text>
        <TodosList /> 
      </View>
    );
  }
}

That's it! Now make sure that the React packager is still up & running and that Edge / Chrome is open on the developer tools. The UWP application should update itself and you should see the list of to-dos being downloaded and rendered:

 

TodosFirstVersion.png

The controls we have defined using JSX have been translated into native UWP controls:

  • Text is now a TextBlock
  • ActivityIndicator is now a ProgressRing
  • FlatList is now a ListView

The nice benefit of the live debugger is that you won't have to redeploy the UWP application every time you make a change. Just change something in the React Native code in Visual Studio Code, hit save and the content of the UWP app will be reloaded to display the updates.

 

That's it! We have our first React Native application running in Windows as a full UWP application!

 

Embedding the React Native component inside a UWP app

Let's move to the next step and see another scenario. What if we want to use the React Native component we have just built not as part of a full React Native application, but inside an existing UWP application? You may have a UWP application already in development, but you may want to integrate a React Native component built by the mobile team for the Android and iOS versions of the same app.

 

Let's start! The first step is to move the React Native component we have built before from a full UWP app to a custom control, that can be reused in other UWP applications. Open the solution created by the React Native for Windows CLI (you'll find it inside the windows folder of your project). Then right click on it and choose Add → New project and select the Windows Runtime Component (Universal Windows) template:

 

WindowsRuntimeComponent.png

 

In this case I'm building a C# component since it's the language I'm most familiar with. However, you could use the C++ template as well since, other than setting up the React Native infrastructure, we aren't actually going to build something. All the content displayed in this control will be provided by the React Native implementation.

 

Feel free to delete the default class that is included in the project, then right click on it and choose Add → New item. Pick User control from the list and give it a meaningful name, like TodosFeedControl.xaml.

Now we need to include inside the newly created user control the React Native for Windows initialization. As first thing, right click on the project, choose Add → Reference and pick up from the list the project called ReactUWP.

 

Now that the React Native for Windows runtime is referenced, we need to add in the XAML file the control which will host the React Native application. First, let's declare the relevant namespace in user control definition:

 

xmlns:react="using:react.uwp"

Then, inside the main Grid, you need to add a ReactControl, which is part of the namespace you have just declared:

 

<Grid>
   <react:ReactControl x:Name="RootElement" />
</Grid>

Now let's move to the code-behind class of the user control. We need to add some code:

 

public sealed partial class TodosFeedControl : UserControl
{
    const string JSFILENAME = "index";
    const string JSCOMPONENTNAME = "TodosFeed";

    public TodosFeedControl()
    {
        this.InitializeComponent();
        LoadReact();
    }

    public void LoadReact()
    {
        InstanceSettings settings;

        settings.UseLiveReload = true;
        settings.UseWebDebugger = true;

        var instance = Instance.Create(JSFILENAME);
        instance.Start(settings);
        RootElement.Instance = instance;

        string initialProps = "{ "
                        + "\"one\":\"1\""
                        + ", \"two\":\"2\""
                        + "}";

        RootElement.InitialProps = initialProps;

        RootElement.JsComponentName = JSCOMPONENTNAME;
        RootElement.StartRender();
    }
}

This is boilerplate code to initialize React Native for Windows. The only relevant parts to highlight are the two constants declared at the top:

  • JSFILENAME defines the name of the JavaScript file which contains the starting point of the React Native app, without the .js extension. In our case, it's the index file.
  • JSCOMPONENTNAME defines the name of the component which acts as a starting point of the application. This string must match the name of the project; in our case it's TodosFeed.

That's it! Now we have a component that we can leverage in a full UWP application. Let's try this but, instead of using a basic UWP app, let's use a real one, to make things more interesting. We're going to use the XAML VanArsdel Inventory Sample, which is an open-source project developed by Microsoft to showcase the usage of the latest and greatest XAML controls in a real product.

 

InventoryApp.png

 

As first step, clone or download the project on your computer, then open the Inventory.sln solution. Now we need to add a reference to the user control we have just created. However, since the React Native for Windows implementation isn't stored in a library or in a NuGet package, we'll need to reference also the same C++ project that are referenced by the UWP application which hosts React Native.

 

To keep things cleaner, I decided to create a solution folder (right click on the solution and choose Add → New Solution Folder), where to store all the project related to React Native. Once you have created it, right click on it and choose Add → Existing project. You will need to reference the following 5 projects, which are all stored in the folder that contains the React Native project.

  • Folly, which is included in the node_modules\react-native-windows\Folly folder.
  • ReactUWP, which is included in the node_modules\react-native-windows\ReactUWP folder.
  • ReactCommon, which is included in the node_modules\react-native-windows\ReactCommon folder.
  • ReactWindowsCore, which is included in the node_modules\react-native-windows\ReactWindowsCore folder.

All the previous project files will have the extension .vcxproj, since they're based on C++. The last and fifth project to reference is the one we have just created to store our user control. In my case, it's called TodosFeed.Component and it's stored in the windows folder. This project's file extension will be, instead, .csproj, since it's based on C#.

 

This is how your solution should look like:

 

InventorySolution.png

Now we have everything we need! We can right click on the Inventory.App project, choose Add → Reference and select the TodosFeed.Component project. We're going to add our React Native component in the main dashboard of the application, along with the other widgets.

 

Dashboard.png

 

We can find the dashboard definition inside the Views → Dashboard → DashboardView.xaml file. Let's first add the namespace of our user control:

 

xmlns:react="using:TodosFeed.Component"

The page contains a GridView control with different panels declared as children. Let's add a new one at the end:

 

<react:TodosFeedControl Margin="12" Width="400" Height="250" />

This is how the full GridView definition should look like:

 

<GridView Grid.Row="2" 
          Margin="6" 
          ItemContainerStyle="{StaticResource GridItemStyle}"
          SelectionMode="None" 
          IsItemClickEnabled="True" ItemClick="OnItemClick">
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <controls:WrapPanel />
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
    <views:CustomersPane Margin="12" 
                             Width="600"
                             Height="250"
                             ItemsSource="{x:Bind ViewModel.Customers, Mode=OneWay}" 
                             Tag="Customers" />

    <views:ProductsPane Margin="12" 
                            Width="400"
                            Height="250"
                            ItemsSource="{x:Bind ViewModel.Products, Mode=OneWay}" 
                            Tag="Products" />

    <views:OrdersPane Margin="12" 
                          Width="400"
                          Height="250"
                          ItemsSource="{x:Bind ViewModel.Orders, Mode=OneWay}" 
                          Tag="Orders" />

    <react:TodosFeedControl Margin="12"
                            Width="400"
                            Height="250" />
</GridView>

That's it. The user control we have just added contains all the logic required to initialize the React Native component, so we don't need to do anything else other adding it to the XAML page.

Now it's time to build and deploy the application. Before doing it, however, we need to make sure that the React packager is up & running, otherwise the React Native component won't be rendered. As such, make sure that you have launched the yarn start command on the React Native project and that your browser is opened on the http://localhost:8081/debugger-ui/ URL.

 

If you have done everything correctly, after logging in on the dashboard you should see this:

 

DashboardWithReact.png

 

Voilà! Now our React Native component is being rendered inside the dashboard, along all the other native UWP controls.

 

Embedding the React Native component inside a Win32 app

Thanks to XAML Islands, we have the opportunity to embed inside a Win32 application a UWP control, either built-in in the platform or a custom one, like the one we have just created to reuse our React Native control. Let's move on and add our component to a WPF application built on top of .NET Core 3.0, since it's the platform that provides the best compatibility with XAML Islands.

 

Create a new solution in Visual Studio 2019 and choose WPF (.NET Core) as project's type:

 

WpfNetCore.png

 

As first step, you need to reference again all the projects required to run React Native and the user control we have created. These are the same ones we have added in the previous scenario: Folly, ReactCommon, ReactUWP, ReactWindowsCore and the custom control TodosFeed.Component.

 

Now we need to setup the whole infrastructure required to support XAML Islands in a WPF application. The official documentation contains a very detailed step-by-step guide, which is available here. As such, I won't repeat all the required steps in this post. The only thing to pay attention is that, compared to the documentation, we already have a project which contains a custom control in our scenario. As such, you can skip the step called Create a custom UWP control. You just need to make sure to add to the project's file the two properties which are required to make it working with a Win32 application.

 

Right click on the TodosFeed.Component project and choose Unload Project. Then right click on it again and choose Edit. Create a new PropertyGroup inside the <Project> element with the following entries:

 

<PropertyGroup>
  <EnableTypeInfoReflection>false</EnableTypeInfoReflection>
  <EnableXBindDiagnostics>false</EnableXBindDiagnostics>
</PropertyGroup>

Then reload the project again and you will be good to go. Just remember to add a reference to the TodosFeed.Component project both to the dummy UWP application and the WPF project.

 

Setup the WPF project

Microsoft provides an easy way to integrate XAML Islands in a WPF application by offering a control that does most of the heavy-lifting for you. The control is called WindowsXamlHost and it's included in the Windows Community Toolkit. To use it, you need to add the NuGet package called Microsoft.Toolkit.Wpf.UI.XamlHost in your WPF application.

The other step is to configure your solution to target a specific platform, since UWP controls can't target the generic Any CPU architecture. As such, right click on the solution in Visual Studio and choose Properties → Configuration Properties → Configuration Manager. Under Active solution platform, choose New, then add x64 or x86, as you prefer.

 

All the projects in the dialog should list, under the Platform column, the same architecture that is defined in the Active solution platform dropdown.

 

CpuArchitecture.png

 

Add the React Native component

Now that the project is setup in the right way, you can add to your WPF application the WindowsXamlHost control we have previously included with the NuGet package. We're going to add it to the MainPage.xaml file of the WPF application. First, you need to add to the Window element the following namespace:

 

xmlns:xaml="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"

Then you can add the control inside the main Grid element:

 

<xaml:WindowsXamlHost InitialTypeName="TodosFeed.Component.TodosFeedControl" />

The InitialTypeName property is set with the full signature of the user control which hosts the React Native component.

Package the application as MSIX

The easiest way to make sure that everything works in the right way with XAML Islands is to package the WPF application as MSIX. However, compared to a traditional application, there are some extra steps to take, in order to make sure that all the files are included in the package in the right way. Make sure to read the section titled Package the app in the documentation and follow all the steps.

Run it!

That's it! As usual, before testing our WPF app, we need to launch the React packager and the local web server. Once everything is up and running, you can right click on the Windows Application Packaging Project and choose Deploy or press CTRL-F5. The WPF application will start and, if you have done everything properly, you will see your WPF application hosting your familiar React Native component:

 

WpfToDos.png

 

Wrapping up

In this (long) blog post we have learned how React Native is a great solution not just to build mobile application, but also Windows experiences. If you're a C# and XAML developer and you're interested in building cross-platform experiences, Xamarin and Xamarin Forms are still the best choice. However, in many cases, you may need to work with a development team with a strong web background and, in such a case, React Native is a great fit. As you have learned in this post, the React Native implementation for Windows is really flexible. Maybe you won't need to build a full UWP application from scratch with React Native, but the framework opens up many opportunities to reuse React Native components built by your web team inside your Windows applications.

 

React Native for Windows is still a work in progress and, as such, the deployment story isn't available yet. Right now, regardless of the way you compile your React Native for Windows project, you always need the Metro packager up & running in order to render the React content. Of course, this isn't the expected experience for the final user. Once the work on the deployment will be completed, you will be able to create a self-contained MSIX package (like for a regular UWP or Win32 packaged application) and publish it on the Store, share it through a website, deploy with enterprise tools like SSCM or Intune, etc. You can see a glimpse of the expected experience by taking a look at the deployment story for the current React Native for Windows version.

 

You can find all the samples mentioned in this article on GitHub.

 

Happy coding!

21 Comments
Copper Contributor

Wow finally React seems to be ultimate solution to building all platform variety of apps. Thanks for sharing. 

Copper Contributor

Awesome @Matteo Pagani 

 

I am trying to get an app working using react-native -windows. I was wondering if any @react-navigation port with windows is available. Do you have any idea ? 

 

Microsoft

Hello, unfortunately react-navigation isn't supported at the moment, since the module provides an implementation only for iOS and Android. You can track the status of the 3rd party modules which are currently being investigated for the porting here: https://github.com/microsoft/react-native-windows/projects/23 

Copper Contributor

Hi

 

Is Modal supported in react-native-windows? I always get an error as follows.

 

RCTModalHostView was not found in UIManager 

Do I have to build a separate component to get this working? 

I am neither able to get Windows Flyout and Popup from react-native-windows. Do you have any working example of this? 

 

 

 

Copper Contributor

Hi @Matteo Pagani 

 

I was trying to get a React Native Component to be run in WPF Application as mentioned here. 

I am getting the following exception when I load the React In Custom Control. Could you please throw some light on what could have gone wrong? 

I doubt that ReactApp.Component project is unable to get the handle of the outer React project. 

 

Code 

 

InstanceSettings settings = new InstanceSettings();
settings.UseLiveReload = true;
settings.UseWebDebugger = true;
settings.EnableDeveloperMenu = true;
var instance = Instance.Create(JSFILENAME);
instance.Start(settings); // THis line is giving exception

 

 

Error 

 

System.Runtime.InteropServices.SEHException
HResult=0x80004005
Message=External component has thrown an exception.
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>

 

 

Microsoft

Hello, let me do some investigations and I'll get back to you. The React Native core went through a few changes since I published this blog post, so this could have affected my sample as well.

Copper Contributor

Thanks @Matteo Pagani 

 

Your response is appreciated. 

I was able to run that. The issue was happening because I was running the app without packaging.  

However, I faced a new issue after that. The app ran and complaining in a red box as a popup. 

 

A better RedBox experience is provided by Microsoft.ReactNative. Consider moving off ReactUWP to Microsoft.ReactNative today!

But I do not see any example of WPF implementing ReactNative with Microsoft.ReactNative. Do you know any project/example done with Microsoft.ReactNative? 

Microsoft

Hello @nahmed215 , take a look at the most recent version of the official sample here: https://github.com/microsoft/react-native-windows-samples/tree/master/samples/TodosFeed/ContosoExpen...

I have updated it a while ago to leverage Microsoft.ReactNative instead of ReactUWP.

 

I hope it helps!

Copper Contributor

Thank you very much. I am going to look at it. 

Copper Contributor

Hi @Matteo Pagani ,

 

I was able to run the projects you mentioned. There were a couple of hurdles that I was able to fix manually.

https://github.com/microsoft/react-native-windows-samples/issues/66

https://github.com/microsoft/react-native-windows-samples/issues/101

 

Now after building TodosFeed and ContosoExpenses. TodosFeed apps work fine but when I execute ConstosoExpenses App (Embedding RN control in  WPF app) I get a runtime error 'Abort has been called'.

 

Any pointers for fixing this. I even tried switching to the latest version of react-native-windows (0.61.9) but the same error. 

 

The image of the App window and error is here : https://postimg.cc/sB3HfY8Z

Microsoft

Hello @nahmed215 ,

unfortunately this is a known issue that started to happen after I've originally published the post. I'm investigating this with the help of the XAML Islands team, but I anticipate I won't be able to share a solution soon. Both me and the team are very busy due to the upcoming Build, so we'll likely resume the investigation after the event.

 

Thanks for your patience!

Copper Contributor

Thanks @Matteo Pagani 

 

I appreciate your response. I hope this should be solved in the next version. 

Copper Contributor

Hi @Matteo Pagani, Is the XAML islands issue fixed now? Do you have any good update to share? 

Microsoft

Hi @nanduahmed unfortunately no, there are still some issues. I'm currently on vacation and I'll get back at the end of the month. I will follow up with the team as soon as I'm back.

 

Thanks for your patience  

Microsoft

Hello @nanduahmed I can confirm that React Native for Windows 0.62 has fixed the problem. If you move your project to the latest React Native version, the XAML Island project will work just fine. I have submitted a PR with the required changes to the sample. In the meantime, if you are eager to give it a try, you can check my fork: https://github.com/qmatteoq/react-native-windows-samples/tree/master/samples/TodosFeed

Copper Contributor

@Matteo Pagani do we have any updated documentation on building/publishing a react native windows app into an appx in a CI/CD environment (specifically Azure DevOps)?  I will be side-loading so even if Store publishing is not ready yet, any docs you can point to would be helpful.

Microsoft

Hello @brodman_apterainc , a React Native for Windows application is, in the end, a UWP app, so the same techniques to do CI/CD for UWP apps will work. You can absolutely publish the app on the Store, as well.

Here, for example, you can see a sample pipeline I'm using on GitHub: ReactNew/pipeline.yml at master · qmatteoq/ReactNew (github.com)

 

You can refer also to this documentation: Set up automated builds for your UWP app - UWP applications | Microsoft Docs

 

Let me know if you're hitting any specific problem and I'll be happy to help.

 

Best

Copper Contributor

Hi @Matteo Pagani

 

I have tried below steps to publish my React Native application for windows:

 

  • Open the solution in Visual Studio
  • Select the Release configuration from the Configuration Manager drop-down.
  • Build the solution. You can now launch without first launching Metro.
  • If you want to build an APPX package to share or publish, use the Project > Publish > Create App Packages... option.

Observations:
For building the app it takes a hell lot of time (more than 30 mins) and after completing build successfully I'm not able to launch my RN application without Metro. It gives me error "A connection with the server could not be established" (see below error screen-shot).

 

After publishing I see there is an react-native application automatically installed into my system with the same name of my application and upon double clicking it I'm getting same error.

 

Error screen-shot:

arun986_0-1675768587038.png

 

Could you please advice me how we can create React Native application for Windows project, standalone package which will work without explicitly running Metro (without running npm start command).

Thanks in advance!

BR,

Arun Rastogi

 

Microsoft

Hello Arun,

regarding the long building time, unfortunately that's expected. When you generate the package for distribution, Visual Studio rebuilds the whole solution from scratch and, since React Native is added through the whole source code, it takes a long time to build the C++ core. Things should improve if and when the team will be able to move the RNW core to NuGet, so that you don't have to rebuild it every time.

Regarding the Metro issue, that's weird. A Release package shouldn't ask you to connect to Metro, since the JS bundle is embedded into the package. Make sure to uninstall all the instances of your application before deploying the Release package, there might be some conflicts because both packages you use for debugging and for distribution share the same unique identifier (the package family name).

 

Best

Copper Contributor

Hi @Matteo Pagani

Thanks for your super quick response.

Regrading the metro issue, I want to elaborate little more, as I did fresh build to rule this out. In my machine there was no previous release package installed. But it still did not work.
Moreover one of my colleague also did same steps and he is getting same issue.

Any pointers to look where is the issue would be much appreciated.

Few more details:

I have used below command to create my react-native application:

  • npx react-native init {projectName} --template react-native@^0.71.0
  • cd {projectName}
  • npx react-native-windows-init --overwrite
  • npx react-native run-windows



    Here is my package.json:

    arun986_0-1675776817172.png

     


    My system specs: Windows 11 OS and Visual Studio 2022 professional

     

    BR,

    Arun Rastogi

      

 

Microsoft

Hello @arun986 ,

I would try to open an issue on the official RNW repository on GitHub, so that the team can help you in diagnosing the issue. From my side, unfortunately, I'm not able to reproduce it. I just tried to create a new RNW 0.71 project and to generate a Release package and I can see the application starting up without having the Metro debugger running in background.

 

Best

Version history
Last update:
‎May 09 2020 08:27 AM
Updated by: