Build your own react in rust.
Introduction
In this blog I am going through on how can you make your own react like library (Or I should say framework because rust won't be so lenient on you๐คฃ), In this blog I'll be showing you JavaScript and Rust code examples side by side.
Disclaimer
This is not an end-to-end clone of react I'll just be showcasing how react puts stuff inside html and how will rust do. and will not cover how it updates current present data in webpage.
Inspiration
Inspiration for this blog is from
and my motivation to not write JS ๐ฃ
Hello World.
Hello World in react.
Default react app.
first let's take a look at default react app. for this first make a folder and inside that folder do
create-react-app ./
here is how folder structure will look like
react-hello/
โโโ .gitignore
โโโ package-lock.json
โโโ package.json
โโโ public/
| โโโ favicon.ico
| โโโ index.html
| โโโ logo192.png
| โโโ logo512.png
| โโโ manifest.json
| โโโ robots.txt
โโโ README.md
โโโ src/
โโโ App.css
โโโ App.js
โโโ App.test.js
โโโ index.css
โโโ index.js
โโโ logo.svg
โโโ reportWebVitals.js
โโโ setupTests.js
we are going to ignore most of the files and look at App.js
, index.js
and index.html
Here is what's happening in App.js
we are just returning a html <h1>
tag that has Hello World!
in it.
// scr/App.js
function App() {
return (
<h1>Hello World!</h1>
);
}
export default App;
Here is what's happening in index.js
// src/index.js
import ReactDOM from 'react-dom/client';
import App from './App';
const domRoot = document.getElementById('root');
const root = ReactDOM.createRoot(domRoot);
root.render(
<App />
);
Writing our plan old JavaScript to get a html element which has an attribute id of name "root"
passing that html element in
ReactDOM.createRoot()
which will do all the fun stuff of react like making a "virtual-dom" and all comparison between new and old code.rendering out
<App />
component from root of ReactDOM.createRoot() function
lets look at index.html
file.
<!--public/index.html-->
<html lang="en">
<head>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
there is one little magic going on of from where is this index.html
file connected to index.js
who's trick I'll tell you now. But for that first build your react app by doing
npm run build
after doing this go to your build/
folder you'll find a index.html file inside that build folder where there magic fails and they have to add script tag (you might notice that its not same index.js that we were editing, well its same same but different ๐คฃ it too is generated on running that build command.)
<script defer="defer" src="/static/js/main.67d6da4b.js">
Thats it thats how react works at its basic.
Custome React app
It's pretty much same as react app only we wont be passing our component in ReactDOM.createRoot()
function instead we'll define our own render and ReactDOM.createRoot()
function we'll doing this in browser itself. so if you have your real react app running open console in browser and type
const myCopm = {
type: "h1",
child: "Hello world! from custom React"
}
function render(root, comp) {
const newEle = document.createElement(comp.type)
newEle.innerHTML = comp.child
root.appendChild(newEle)
}
const domRoot = document.getElementById('customeRoot');
render(domRoot, myComp)
Also add a div
tag in html with id customeRoot
And there you have it you have just made your own react, the output should look something like this
Note: Since I have build my own render function I get to decide how and what type I am going to expect its parameters this same component wont work in react because react is not expecting this type of parameters. What I have shown is trick of react + other libraries such as babel and webpack. To check the real tricks refer build folder.
Hello World in Leptos.
Default leptos app
Now let's look at rust web library leptos it is similar to react but in rust.
For this make a folder leptos-hello
and cd
into it and do
cargo init
cargo install trunk
cargo add leptos --features=csr,nightly
rustup toolchain install nightly
rustup override set nightly
this will install leptos in current project (trunk is similar to webpack in rust it is responsible to insert your rust code in index.html)
Also you'll need a index.html
file in top level of you project as trunk will use that index file (This setting can be changed in trunk config.toml file, let me know if you would want me to make a blog on same) this is how your project would look like.
leptos-hello/
โโโ Cargo.lock
โโโ Cargo.toml
โโโ index.html
โโโ src/
| โโโ main.rs
now lets open up main.rs
file
use leptos::*;
fn main() {
mount_to_body(|| view! { <h1>"Hello World!"</h1> })
}
Yeah this is all the code you need to make "Hello World" leptos app pretty neat right? ๐
its just adding the h1
tag inside body of our index.html file.
No, you dont need div
with id root here this'll work just fine to run this go to current folder terminal and type
trunk serve --open
now check localhost:8080
you'll see "Hello World!"
Custome Leptos app
we'll be using web_sys
to make custome app as this library is responsible to convert our rust code to javascript and make connection between our wasm code and browser this can be imported from leptos as well
Open up same main.rs file and lets start editing it.
use leptos::*;
fn main() {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let body = document.body().unwrap();
let h1 = document.create_element("h1").unwrap();
h1.set_inner_html("Hello World! from custom leptos");
body.append_child(&h1).unwrap();
}
The code is pretty self explanatory itself but in a gist its grabing window then from window getting document using that its creating a h1
element and adding innerHTML
in it as we did in our react app now we will add that h1 element as a child of our body which we can get from document. Thats all. now you have created your custome leptos app easy right.
to run this use same command.
trunk serve --open
You'll see something like this in browser
you can look at wasm code in script (I didn't understand it ๐ค๐ซก)
All right. Thats it for this blog, Let me know if you have any questions post them in comments.
Thanks for the read.
Have a great day bye-bye