If you know React, you already know 80% of Ivy. The mental model is identical - components, hooks, declarative UI - just expressed in C# instead of JavaScript. No JSX, no bundlers, no node_modules. Just your existing React intuition applied to a full-stack C# framework.
The Familiar Patterns
Components Are Views
In React, you build with functional components. In Ivy, you build with Views:
React:
function UserCard({ name, email }) {
return (
<div className="card">
<h2>{name}</h2>
<p>{email}</p>
</div>
);
}
Ivy:
public class UserCard : ViewBase
{
public required string Name { get; init; }
public required string Email { get; init; }
public override object? Build()
{
return new Card()
| Text.H2(Name)
| Text.P(Email);
}
}
Same concept, different syntax. The Build() method is your render function.
Hooks Work the Same Way
This is where Ivy really shines for React developers. The hooks you know and love have direct equivalents:
| React | Ivy | Purpose |
|---|---|---|
useState |
UseState |
Local component state |
useEffect |
UseEffect |
Side effects with dependencies |
useContext |
UseService or UseContext |
Dependency injection |
useRef |
UseRef |
Mutable references that don't trigger rebuild |
React:
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
Ivy:
public class Counter : ViewBase
{
public override object? Build()
{
var count = UseState(0);
UseEffect(() => {
Console.WriteLine($"Count: {count.Value}");
}, [count]);
return new Button($"Count: {count.Value}",
onClick: _ => count.Set(count.Value + 1));
}
}
The mental model is identical. State changes trigger re-renders. Effects run when dependencies change. You already understand this.
What's Different (and Better)
No Build Pipeline
React requires: npm, webpack/vite, babel, node_modules, package.json, build scripts...
Ivy requires:
dotnet watch
That's it. Hot reload included. No configuration needed.
No API Layer Needed
In React, you typically:
- Build your UI
- Create API endpoints
- Fetch data with useEffect + fetch/axios
- Handle loading/error states
- Sync frontend and backend types
In Ivy, you just... use your data:
public override object? Build()
{
var db = UseService<MyDbContext>();
var users = db.Users.Where(u => u.IsActive).ToList();
return users.ToTable();
}
Your C# code runs on the server. Direct database access. No REST endpoints to maintain. No type mismatches between frontend and backend.
Server-Side State = Security
In React, state lives in the browser. Sensitive logic requires careful API design.
In Ivy, state lives on the server. The browser only sees rendered widgets — never your business logic, database queries, or sensitive data. Updates to the widget tree is sent as patches efficiently over websocket.
Layout Composition
React developers love composition. Ivy uses the | operator for the same pattern:
React:
<Layout direction="vertical" gap={4}>
<Header />
<Sidebar />
<Content />
</Layout>
Ivy:
Layout.Vertical().Gap(4)
| new Header()
| new Sidebar()
| new Content()
The pipe operator (|) is syntactic sugar for adding children. It's composable, readable, and feels natural once you use it.
Event Handling
React's event model translates directly:
React:
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
<button onClick={() => handleSubmit()}>
Submit
</button>
Ivy:
var search = UseState("");
return Layout.Verical()
| search.ToTextInput();
| new Button("Submit", onClick: _ => HandleSubmit(search.Value))
Same concepts: controlled inputs, event handlers, state updates triggering re-renders.
Context and Services
React:
const theme = useContext(ThemeContext);
Ivy:
var theme = UseService<IThemeProvider>();
Ivy uses .NET's built-in dependency injection, which is more powerful than React Context for complex applications.
Async
Ivy handles async naturally:
public override object? Build()
{
var users = UseState<List<User>>([]);
var loading = UseState(true);
var userService = UseService<UserService>();
UseEffect(async () => {
var data = await userService.GetUsersAsync();
users.Set(data);
loading.Set(false);
}, []);
if (loading.Value) return new Skeleton();
return users.Value.ToTable();
}
Getting Started
If you're a React developer ready to try Ivy:
First, make sure you have installed the .NET 9 SDK.
dotnet tool install -g Ivy.Console
ivy init --hello
dotnet watch
You'll have a running app with hot reload in seconds. Open the code, and you'll feel right at home.
The Bottom Line
Ivy isn't trying to replace React—it's bringing React's brilliant component model to the .NET ecosystem. If your team knows C# and you're tired of maintaining separate frontend and backend codebases, Ivy lets you use your React intuition without the JavaScript toolchain complexity.
Your mental model transfers. Your patterns transfer. You just write C# instead.
Resources:
