I have created a simple project that demonstrates how to set up a Windows desktop application using WebView2 to host a React frontend, with two‑way communication between the React app and the C# WPF application.
You can choose from the following versions:
- .NET 6+ SDK
- Node.js 18+
- WebView2 Runtime
- React Frontend
Here this is my set-up you can consult Create React App
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
App.tsx
import { useState, useEffect } from 'react'
function App() {
const [isWebView2, setIsWebView2] = useState(false)
const [message, setMessage] = useState('Waiting for host...')
useEffect(() => {
setIsWebView2(!!(window as any).chrome?.webview)
window.addEventListener('message', (event) => {
const data = JSON.parse(event.data)
if (data.type === 'UPDATE') {
setMessage(data.text)
}
})
}, [])
const sendToHost = () => {
if (isWebView2) {
(window as any).chrome.webview.postMessage(JSON.stringify({
type: 'BUTTON_CLICK',
data: 'Hello from React!'
}))
}
}
return (
<div style={{ padding: '20px', fontFamily: 'Arial' }}>
<h1>WebView2 + React Demo</h1>
<div style={{
padding: '10px',
background: isWebView2 ? '#d4edda' : '#f8d7da',
borderRadius: '5px',
marginBottom: '20px'
}}>
Environment: {isWebView2 ? 'WebView2' : 'Browser'}
</div>
<button
onClick={sendToHost}
style={{
padding: '10px 20px',
background: '#007bff',
color: 'white',
border: 'none',
borderRadius: '5px'
}}
>
Send to Host
</button>
<div style={{ marginTop: '20px', padding: '10px', background: '#f8f9fa' }}>
<strong>Host Message:</strong> {message}
</div>
</div>
)
}
export default App
Start React
npm run dev
- C# Host Application
Create Project
dotnet new winforms -n WebView2Host
cd WebView2Host
dotnet add package Microsoft.Web.WebView2
dotnet add package System.Text.Json
MainForm.cs
using Microsoft.Web.WebView2.WinForms;
using Microsoft.Web.WebView2.Core;
using System.Text.Json;
public partial class MainForm : Form
{
private WebView2 webView;
private Button sendBtn;
public MainForm()
{
InitializeComponent();
SetupWebView();
}
private void InitializeComponent()
{
this.Size = new Size(800, 600);
this.Text = "WebView2 + React Demo";
sendBtn = new Button
{
Text = "Send to React",
Size = new Size(150, 30),
Location = new Point(10, 10)
};
sendBtn.Click += (s, e) => SendToReact();
webView = new WebView2 { Dock = DockStyle.Fill };
var panel = new Panel { Height = 50, Dock = DockStyle.Top };
panel.Controls.Add(sendBtn);
this.Controls.Add(webView);
this.Controls.Add(panel);
}
private async void SetupWebView()
{
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.WebMessageReceived += (s, e) =>
{
var message = JsonSerializer.Deserialize<dynamic>(e.TryGetWebMessageAsString());
MessageBox.Show($"React says: {message}");
};
webView.CoreWebView2.Navigate("http://localhost:5173");
}
private void SendToReact()
{
var message = new { type = "UPDATE", text = $"Hello from C#! {DateTime.Now:HH:mm:ss}" };
webView.CoreWebView2.PostWebMessageAsString(JsonSerializer.Serialize(message));
}
}
Program.cs
namespace WebView2Host;
static class Program
{
[STAThread]
static void Main()
{
ApplicationConfiguration.Initialize();
Application.Run(new MainForm());
}
}
- Run
Terminal 1: React
npm run dev
Terminal 2: C#
dotnet run
- Test
- Click "Send to Host" in React → C# shows message
- Click "Send to React" in C# → React updates message
- Two-way communication working!
Quick Test (Browser Only)
Open React app → F12 Console → Paste:
// Simulate host message
window.postMessage('{"type":"UPDATE","text":"Test from console!"}', '*');
Build Production
React
npm run build
C# (single exe)
dotnet publish -c Release -r win-x64 --self-contained -p:PublishSingleFile=true
Common Issues
- WebView2 not found: Install WebView2 Runtime
- React not loading: Check if dev server is running
- Messages not working: Open F12 to debug
This is just a reference approach, so feel free to review and comment on it. I’ve also attached some official Microsoft documentation here
- WebView2 official communication guide: https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/communication
- window.chrome.webview.postMessage (recommended way): https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl#postwebmessa…
- ExecuteScriptAsync + WebMessageReceived sample: https://learn.microsoft.com/en-us/microsoft-edge/webview2/samples/webview2apisample
The method I gave you earlier (postMessage + ExecuteScriptAsync) is exactly the one Microsoft recommends as the simplest and most reliable in all of the above official docs.
Hopefully, the above information will help you solve the problem.