Reactive.Wasm 3.0.1

dotnet add package Reactive.Wasm --version 3.0.1
                    
NuGet\Install-Package Reactive.Wasm -Version 3.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Reactive.Wasm" Version="3.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Reactive.Wasm" Version="3.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Reactive.Wasm" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Reactive.Wasm --version 3.0.1
                    
#r "nuget: Reactive.Wasm, 3.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Reactive.Wasm@3.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Reactive.Wasm&version=3.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Reactive.Wasm&version=3.0.1
                    
Install as a Cake Tool

Build #yourfirstpr alternate text is missing from this package README image NuGet codecov

<br> <a href="https://github.com/reactiveui/reactiveui"> <img width="160" heigth="160" src="https://raw.githubusercontent.com/reactiveui/styleguide/master/logo/main.png"> </a> <br>

System.Reactive for WebAssembly

This package provides WebAssembly-specific implementations for System.Reactive, designed to be integrated into ReactiveUI and ReactiveUI.Uno projects to enable optimal reactive programming in WebAssembly environments. It provides platform-aware scheduler selection and WASM-optimized concurrency abstractions for cross-platform applications targeting Blazor WebAssembly and other WASM hosts.


NuGet Packages

To get started, install the following package into your WebAssembly project.

Platform NuGet
WebAssembly NuGet

Tutorial: Integrating with ReactiveUI Projects

Welcome to the System.Reactive.Wasm integration guide! This tutorial shows you how to integrate this package into ReactiveUI and ReactiveUI.Uno projects to enable optimal reactive programming across platforms, with special support for WebAssembly environments like Blazor WebAssembly.

The most common usage of System.Reactive.Wasm is not as a standalone library, but as an integration component that provides platform-aware scheduler selection for cross-platform ReactiveUI applications.

Chapter 1: Basic Integration with ReactiveUI

The primary integration scenario involves configuring ReactiveUI's scheduler selection to use appropriate schedulers based on the target platform.

1. Installation

Add the Reactive.Wasm package to your ReactiveUI project that targets WebAssembly:

<PackageReference Include="Reactive.Wasm" Version="[latest-version]" />
<PackageReference Include="ReactiveUI" Version="[latest-version]" />
2. Platform-Aware Scheduler Configuration

Configure your dependency injection to select the appropriate scheduler based on the platform. This is the most common integration pattern:

using ReactiveUI;
using Microsoft.Extensions.DependencyInjection;
using System.Reactive.Concurrency;

public static void ConfigureServices(IServiceCollection services)
{
    // Configure platform-aware scheduler selection
    // WebAssembly does not support Threads for .NET5/.NET6+
    _ = services
        .AddSingleton<IScheduler>(static provider =>
        {
            return provider.GetRequiredService<Platform>() switch
            {
                Platform.WebAssembly => RxApp.MainThreadScheduler,
                _ => RxApp.TaskpoolScheduler,
            };
        });

    // Register your ViewModels and other services
    services.AddTransient<MyViewModel>();
}
3. Platform Detection

Create a simple platform detection service to identify WebAssembly environments:

public enum Platform
{
    WebAssembly,
    Desktop,
    Mobile
}

public interface IPlatformService
{
    Platform CurrentPlatform { get; }
}

public class PlatformService : IPlatformService
{
    public Platform CurrentPlatform => DetectPlatform();

    private static Platform DetectPlatform()
    {
#if WEBASSEMBLY
        return Platform.WebAssembly;
#elif ANDROID || IOS
        return Platform.Mobile;
#else
        return Platform.Desktop;
#endif
    }
}

Chapter 2: ReactiveUI.Uno Integration

For Uno Platform projects using ReactiveUI, the integration follows a similar pattern with some Uno-specific considerations.

1. Uno Platform Project Setup

In your Uno Platform project, configure the scheduler selection in your App.xaml.cs:

using ReactiveUI;
using Microsoft.Extensions.DependencyInjection;
using System.Reactive.Concurrency;

public partial class App : Application
{
    public App()
    {
        this.InitializeComponent();
        ConfigureServices();
    }

    private void ConfigureServices()
    {
        var services = new ServiceCollection();

        // Platform-aware scheduler configuration for Uno
        services.AddSingleton<IScheduler>(provider =>
        {
#if __WASM__
            // WebAssembly platform uses MainThreadScheduler
            return RxApp.MainThreadScheduler;
#else
            // Other Uno platforms use TaskpoolScheduler
            return RxApp.TaskpoolScheduler;
#endif
        });

        // Register ReactiveUI services
        services.AddSingleton<IViewLocator, DefaultViewLocator>();

        // Register your ViewModels
        services.AddTransient<MainViewModel>();
    }
}
2. ViewModel Integration

Your ViewModels work seamlessly across all Uno platforms with the configured schedulers:

using ReactiveUI;
using System.Reactive;
using System.Reactive.Linq;

public class MainViewModel : ReactiveObject
{
    private string _message = "Hello Uno!";

    public string Message
    {
        get => _message;
        set => this.RaiseAndSetIfChanged(ref _message, value);
    }

    public ReactiveCommand<Unit, Unit> UpdateMessageCommand { get; }

    public MainViewModel()
    {
        UpdateMessageCommand = ReactiveCommand.CreateFromTask(async () =>
        {
            // This will use the appropriate scheduler based on platform
            Message = $"Updated at {DateTime.Now:HH:mm:ss}";

            // Demonstrate reactive stream that works across platforms
            await Observable.Timer(TimeSpan.FromSeconds(1))
                .Select(_ => $"Delayed update at {DateTime.Now:HH:mm:ss}")
                .Do(msg => Message = msg);
        });
    }
}

Advanced Usage

The following sections cover advanced scenarios where you need direct access to WASM-specific reactive features. Most applications using ReactiveUI or ReactiveUI.Uno won't need these advanced techniques.

Direct WASM Scheduler Usage

The WasmScheduler is specifically designed to work efficiently with the WebAssembly runtime, providing optimal scheduling for both immediate and delayed operations.

1. Using the WASM Scheduler Directly
using System.Reactive.Concurrency;

public class SchedulerExample
{
    public void DemonstrateWasmScheduler()
    {
        var scheduler = WasmScheduler.Default;

        // Schedule immediate work
        scheduler.Schedule(() => Console.WriteLine("Immediate work executed"));

        // Schedule delayed work
        scheduler.Schedule(TimeSpan.FromSeconds(2), () =>
            Console.WriteLine("Delayed work executed after 2 seconds"));

        // Schedule periodic work
        var periodicWork = scheduler.SchedulePeriodic(TimeSpan.FromSeconds(1), () =>
            Console.WriteLine($"Periodic work executed at {DateTime.Now:HH:mm:ss}"));
    }
}
2. Reactive Streams with Custom Scheduling
using System.Reactive.Linq;
using System.Reactive.Concurrency;

public class CustomSchedulingExample
{
    public void CreateScheduledStream()
    {
        var wasmScheduler = WasmScheduler.Default;

        // Create an observable that uses the WASM scheduler
        var scheduledStream = Observable.Generate(
            0,                           // Initial state
            x => x < 10,                // Continue condition
            x => x + 1,                 // Iterator
            x => $"Value: {x}",        // Result selector
            x => TimeSpan.FromMilliseconds(500), // Time selector
            wasmScheduler)              // Use WASM scheduler
            .Subscribe(value => Console.WriteLine(value));
    }
}

Platform Enlightenment Provider (Advanced)

For scenarios where you need manual control over the reactive platform services, you can use the Platform Enlightenment Provider directly:

using System.Reactive.PlatformServices;

public static void Main(string[] args)
{
    // Enable WASM-specific reactive extensions
#pragma warning disable CS0618 // Type or member is obsolete
    PlatformEnlightenmentProvider.Current.EnableWasm();
#pragma warning restore CS0618 // Type or member is obsolete

    // ... rest of your application initialization
}

Performance Optimization Techniques

WebAssembly has unique performance characteristics. Here are some best practices for reactive programming in WASM environments.

1. Efficient Observable Chains
public class PerformanceOptimizedExample
{
    public IObservable<string> CreateOptimizedStream(IObservable<int> source)
    {
        return source
            .Where(x => x > 0)           // Filter early
            .Buffer(TimeSpan.FromMilliseconds(100)) // Batch operations
            .Where(buffer => buffer.Count > 0)      // Avoid empty batches
            .Select(buffer => $"Processed {buffer.Count} items")
            .DistinctUntilChanged()      // Avoid duplicate notifications
            .ObserveOn(WasmScheduler.Default); // Ensure WASM scheduling
    }
}
2. Memory Management in WASM
using System.Reactive.Disposables;

public class MemoryEfficientExample : IDisposable
{
    private readonly CompositeDisposable _disposables = new();

    public void SetupReactiveStreams()
    {
        // Always dispose of subscriptions in WASM to prevent memory leaks
        var subscription1 = Observable.Timer(TimeSpan.FromSeconds(1))
            .Subscribe(x => Console.WriteLine($"Timer: {x}"));

        var subscription2 = Observable.FromEvent<EventArgs>(
            h => SomeEvent += h,
            h => SomeEvent -= h)
            .Subscribe(x => Console.WriteLine("Event received"));

        // Add to composite disposable for easy cleanup
        _disposables.Add(subscription1);
        _disposables.Add(subscription2);
    }

    public event EventHandler<EventArgs>? SomeEvent;

    public void Dispose()
    {
        _disposables.Dispose();
    }
}

Direct Framework Integration (Advanced)

System.Reactive.Wasm works seamlessly with various WASM frameworks.

1. Blazor WebAssembly Integration
@page "/reactive-demo"
@using System.Reactive.Linq
@using System.Reactive.Subjects
@implements IDisposable

<h3>Reactive WASM Demo</h3>
<p>Current Time: @currentTime</p>
<p>Counter: @counter</p>

@code {
    private string currentTime = "";
    private int counter = 0;
    private IDisposable? timeSubscription;
    private IDisposable? counterSubscription;

    protected override void OnInitialized()
    {
        // Create a time stream
        timeSubscription = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1))
            .Select(_ => DateTime.Now.ToString("HH:mm:ss"))
            .Subscribe(time =>
            {
                currentTime = time;
                InvokeAsync(StateHasChanged);
            });

        // Create a counter stream
        counterSubscription = Observable.Timer(TimeSpan.Zero, TimeSpan.FromMilliseconds(100))
            .Subscribe(tick =>
            {
                counter = (int)tick;
                InvokeAsync(StateHasChanged);
            });
    }

    public void Dispose()
    {
        timeSubscription?.Dispose();
        counterSubscription?.Dispose();
    }
}

This tutorial has covered the basics of getting started with System.Reactive.Wasm. You've learned how to set up your project, use the WASM scheduler, optimize performance, and integrate with WASM frameworks. From here, you can explore more advanced System.Reactive features, all optimized for WebAssembly environments.


Thanks

We want to thank the following contributors and libraries that help make System.Reactive.Wasm possible:

Core Libraries

  • System.Reactive: Reactive Extensions for .NET - The foundation of reactive programming in .NET.
  • Splat: Splat - Cross-platform utilities and service location.
  • Mono Runtime: The Mono WebAssembly runtime that enables .NET in WebAssembly environments.
  • Uno.Rx.NET: Uno.Rx.NET - Original implementation that inspired this project.

Sponsorship

The core team members, ReactiveUI contributors and contributors in the ecosystem do this open-source work in their free time. If you use System.Reactive.Wasm, a serious task, and you'd like us to invest more time on it, please donate. This project increases your income/productivity too. It makes development and applications faster and it reduces the required bandwidth.

Become a sponsor.

This is how we use the donations:

  • Allow the core team to work on System.Reactive.Wasm
  • Thank contributors if they invested a large amount of time in contributing
  • Support projects in the ecosystem

Support

If you have a question, please see if any discussions in our GitHub Discussions or GitHub issues have already answered it.

If you want to discuss something or just need help, here is our Slack room, where there are always individuals looking to help out!

Please do not open GitHub issues for support requests.


Contribute

System.Reactive.Wasm is developed under an OSI-approved open source license, making it freely usable and distributable, even for commercial use.

If you want to submit pull requests please first open a GitHub issue to discuss. We are first time PR contributors friendly.

See Contribution Guidelines for further information how to contribute changes.


License

System.Reactive.Wasm is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Reactive.Wasm:

Package Downloads
ReactiveUI.Blazor

Contains the ReactiveUI platform specific extensions for Blazor

ReduxSimple.Wasm

Simple Stupid Redux Store using Reactive Extensions, and a stupid adjust for it work on Wasm

H.ReactiveUI.Uno.WinUI

Contains the ReactiveUI platform specific extensions for Uno WinUI

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on Reactive.Wasm:

Repository Stars
reactiveui/ReactiveUI
An advanced, composable, functional reactive model-view-viewmodel framework for all .NET platforms that is inspired by functional reactive programming. ReactiveUI allows you to abstract mutable state away from your user interfaces, express the idea around a feature in one readable place and improve the testability of your application.
Version Downloads Last Updated
3.0.1 163 9/8/2025
2.1.2 110,165 2/18/2024
2.1.1-ge9f08acb98 357 2/18/2024
1.2.2 849,638 1/19/2020
1.2.1 5,713 1/1/2020
1.0.1-preview.12 1,226 9/19/2019
1.0.1-preview.8 1,475 6/25/2019
1.0.1-preview.3 430 6/16/2019
1.0.1-preview.1 436 6/16/2019