Skip to content

Instantly share code, notes, and snippets.

@Nathan-Franck
Last active February 7, 2024 19:18
Show Gist options
  • Save Nathan-Franck/0df9b8b42f07c548d0ec5933169b1f70 to your computer and use it in GitHub Desktop.
Save Nathan-Franck/0df9b8b42f07c548d0ec5933169b1f70 to your computer and use it in GitHub Desktop.
Theoretical framework for a UI library in Zig that mirrors a bit of what React does
// Theoretical framework for a UI library in Zig that mirrors a bit of what React does
const std = @import("std");
fn Store(T: type) type {
return struct {
value: T,
fn setValue(self: *@This(), value: T) void {
self.value = value;
// TODO: Call back to the framework to start re-rendering
}
};
}
fn Structure(components: type) type {
return union {
div: struct { text: []const u8, callbacks: ?type = null },
component: components,
};
}
const AppStructure = Structure(union {
Report: Report,
});
pub const Report = struct {
// settings provided to the component by the parent:
user_message: []const u8,
// Framework expects a Component decl to be a valid component.
pub const Component = struct {
// State retrieved from the backend store:
my_integer: Store(i32),
// Framework expects a render function to be a valid component.
fn render(self: @This(), allocator: std.mem.Allocator, settings: Report) Structure {
return .{
.div = .{
.text = std.fmt.allocPrint(allocator, "The state's number is {d}, here's a setting {s}", .{
self.my_integer.value,
settings.user_message,
}),
// Callbacks struct can provide a bunch of functions that the Framework can find to call.
.callbacks = struct {
fn onClick(component: Component) void {
component.my_integer.setValue(5);
}
},
},
};
}
};
};
// This is the equivelant to the following react code
// ```jsx
// (user_message) => {
// const [my_integer, setMyInteger] = useState(0);
// return <div on_click = {() => setMyInteger(5)}>The state's number is {params.my_integer}, here's a setting {self.user_message}</div>
// }
// ```
// Obviously, the react code is more concise! You'd have to write a lot more code to get the same functionality in Zig.
// The point though is that you can write a lot of the same functionality in Zig as you can in React, and you can do it in a way that is type safe and has no runtime overhead.
// React even has some weird edge cases that Zig doesn't have, like the fact that you can't use a hook inside a conditional statement, but you can use a function that returns a hook inside a conditional statement.
// Zig doesn't have that problem, because it doesn't have hooks, it just has functions and types.
const my_app = []const AppStructure{
.{ .div = .{ .text = "test" } },
.{ .component = .{ .Report = .{ .user_message = "hello" } } },
.{ .div = .{ .text = "test" } },
.{ .component = .{ .Report = .{ .user_message = "hello2" } } },
};
// This is the equivelant to the following react code
// ```jsx
// <div>test</div>
// <Report user_message="hello" />
// <div>test</div>
// <Report user_message="hello2" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment