Last active
February 7, 2024 19:18
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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