Windows Reactor - #4479
Conversation
5474ac5 to
766fba6
Compare
766fba6 to
a213f1d
Compare
|
Looking at your benchmarks: The C# AOT numbers don't make sense to me (my non-trivial WinUI 3 AOT app for all three architectures take 6 minutes to build, and takes up ~50 MB of disk space). I think that the AOT version might have actually been self-contained rather than AOT compiled. |
Yh these stats are funny. Rust would out perform C# of course but not by this much. |
|
There are some internal discussions about deployment size, now that I have created a table. Stay tuned. 🙃 The actual numbers aren't that important - what matters is they were all measured on the same (old) machine. |
It's getting fixed 😄 (the app and benchmarks). We're working with the reactor team to push some updated numbers. |
|
Are we going to take the same wild ride that react did from |
|
Is there an API to use the widgets without the reactivity layer? I'm interested in doing cross-platform UI, and parts of this look like they could be a great foundation for the window part of a "react native in rust". But in that case you'd probably want to cross-platform framework to own the reactivity and state management... |
Interesting question. Rust's type system eliminates some classes of bugs the React Compiler catches (use-after-move, data races), and our reconciler already skips unchanged subtrees via |
Yes, |
|
when I This error occurs
|
|
Yes, Rafael Rivera (@riverar) is working on a fix for this: #4487 You can obviously work around this (by cloning the repo) but the PR should resolve this pain point permanently. |
|
|
|
The gallery app runs, but when I try to run the demo code or some more complicated code I get the following errors. Demo Code ErrorS D:\repos\winui-reactor-playground> cargo run
Compiling winui-reactor-playground v0.1.0 (D:\repos\winui-reactor-playground)
error[E0271]: expected `app` to return `Element`, but it returns `impl Into<Element>`
--> src\main.rs:4:39
|
4 | App::new().title("sample").render(app)
| ------ ^^^ expected `Element`, found opaque type
| |
| required by a bound introduced by this call
...
7 | fn app(cx: &mut RenderCx) -> impl Into<Element> {
| ------------------ the found opaque type
|
= note: expected enum `windows_reactor::Element`
found opaque type `impl Into<windows_reactor::Element>`
note: required by a bound in `windows_reactor::App::render`
--> C:\Users\maste\.cargo\git\checkouts\windows-rs-a5de4a2dc783ec71\b9e91e0\crates\libs\reactor\src\app.rs:227:62
|
225 | pub fn render<F>(self, f: F) -> Result<()>
| ------ required by a bound in this associated function
226 | where
227 | F: Fn(&mut crate::core::render_context::RenderCx) -> crate::core::element::Element
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `App::render`
For more information about this error, try `rustc --explain E0271`.
error: could not compile `winui-reactor-playground` (bin "winui-reactor-playground") due to 1 previous error error when running custom codePS D:\repos\music-caster\migration-bootstrapper> cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s
Running `target\debug\MigrationBootstrapper.exe`
windows_reactor: Application::Start failed: Error { code: HRESULT(0x80040154), message: "Class not registered" }
Error: Error { code: HRESULT(0x80040154), message: "Class not registered" }
error: process didn't exit successfully: `target\debug\MigrationBootstrapper.exe` (exit code: 1) |
|
Elijah Lopez (@elibroftw) please share a minimal repro in a new issue and I'll be happy to take a look. |
|
Elijah Lopez (@elibroftw) regarding your demo code error, I ran into this exact issue as well when trying out the examples. The error is misleading at first glance because it looks like a generic type mismatch, but the fix is straightforward. Kenny Kerr (@kennykerr)'s intro to windows-reactor post (first comment of this PR) and some docs show the render function signature as: fn app(cx: &mut RenderCx) -> impl Into<Element> {But if you check pub fn render<F>(self, f: F) -> Result<()>
where
F: Fn(&mut RenderCx) -> Element + Send + 'static,It requires a concrete To fix, just change the return type of your view function to fn app(cx: &mut RenderCx) -> Element {
// ...
vstack((...))
.spacing(8.0)
.into() // ← converts the builder into Element
}You can see this pattern in the working sample apps in the repo, like the calendar_view example: fn app(cx: &mut RenderCx) -> Element {
let (count, set_count) = cx.use_state(0_u32);
let bump = move || set_count.call(count + 1);
vstack((
calendar_view().today_highlighted(true).on_changed(bump),
text_block(format!("Selection changed {count} time(s)")),
))
.spacing(8.0)
.into()
}In short: always return |
|
Uzair Mohammed (@gamersekofy) good catch! I've updated the PR description to match the latest changes in the |
|
This is great, but I would prefer a signals-based approach to reactivity inspired by SolidJS, which allows fine-grained reactivity and avoids the need to compute differences. This avoids taking the same wild ride that react did from use_memo, use_callback to automatic memoization as pointed out by Tushar (@tusharsnx). |
|
This looks awesome! Are there any plans to add full support for animations? Currently it looks like animations are quite limited, and the gallery example isn't even faithful to the C# WinUI 3 Gallery that has a page switching animation. I also noticed that opening the gallery example starts with a black screen, then snaps to the mica background with the content. For a proper app, I think it's important that the app either waits for the content to render before making the window visible, or else at least open the window with Mica from the very start. |
Windows Reactor is a UI library for Rust developers targeting WinUI 3 to deliver native, efficient Windows experiences.
Overview
windows-reactorbrings a React-like component model to native Windows desktop apps:use_state,use_reducer,use_effect,use_context,use_memo,use_callback,use_resource, and moreuse_resourceanduse_mutationfor background data loadingThemeRefbrush bindingsGetting Started
Prerequisites
Creating a new app
Add the dependency:
Add the build step:
Write your app:
Running the samples
Performance
Compared to the equivalent C# Reactor gallery app (measured 2026-05-27):
Special Thanks
Thanks to Chris Anderson for kickstarting this project and convincing me to give WinUI another try. Chris is the brains behind Reactor for C#. And I couldn't have done this without Rafael Rivera whose knowledge of Windows internals and WinUI continues to impress.
This builds on a mountain of work in
windows-rsto optimize code generation, build time, and ergonomics. Over the last few weeks alone, the bindgen pipeline gained method-level filtering and mixed allow/deny lists with vtable demotion so thatwindows-reactorcan generate only the exact COM surface it needs — no dead vtable slots, no unused methods. Delegate code gen was minimized to emit void-returning handlers with direct S_OK returns, and event registration now accepts closures directly with a non-generic EventRevoker. Two new crates landed:windows-referencefor zero-overheadIReference<T>boxing (used throughout the reactor for nullable property values) andwindows-timefor idiomaticTimeSpan/DateTimeconversions. The metadata reader was simplified by merging TypeIndex and ItemIndex, and the tokenizer switched to thequotecrate — both reducing bindgen build time. Even if you're not interested in UI development, the profiling that went into this project greatly improved the corewindows-*crates as well.