React + Rust + Wasm: DOM Manipulation

Neo Quest | Nikhil Gupta / October 23, 2022
3 min read
Summary
In this article, we will manipulate the DOM in our React application from our Rust WASM library. We will build on the previous tutorial available here.
Add web-sys to our Rust dependencies
We will use web-sys
to interact with the DOM. Let's add it to our Cargo.toml and activate associated features:
# Cargo.toml
[package]
name = "rust-wasm-lib"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.83"
[dependencies.web-sys]
version = "0.3.4"
features = [
'Document',
'Element',
'HtmlElement',
'Node',
'Window',
]
DOM Manipulation using Rust
Last time, we exposed a function to add two numbers in Rust but the result was added to the screen in the react app. Now, let's modify our lib.rs
to expose another function that will automatically show the result on screen.
#[wasm_bindgen]
pub fn addAndShow(a: i32, b: i32) -> Result<(), JsValue> {
let window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window");
let body = document.body().expect("document should have a body");
let element = document.create_element("p")?;
element.set_text_content(Some(&format!("{} + {} = {}", a, b, a + b)));
body.append_child(&element)?;
Ok(())
}
Let's go through the code step-by-step.
- Expose a function called
addAndShow
that takes two integers and returns a Result - Get the global
window
usingweb_sys
API - Get the document from this window
- Get the body for this document
- Create a DOM element with a
p
tag - Set the text to be the equation
a + b = c
using theformat
macro - Append the element to the body
- Set the Result to success
Build the new wasm library
Let's run wasm-pack again to build the updated library
wasm-pack build --target web
Call the new function from the demo app
Finally, let's call the exported addAndShow
function from our App.ts
file like so:
// App.ts
import React, { useEffect } from 'react';
import init, { addAndShow } from "rust-wasm-lib";
import './App.css';
function App() {
useEffect(() => {
init().then(() => {
addAndShow(3, 4);
});
}, [])
return (
<div className="App">
</div>
);
}
export default App;
Now, if you run the updated app, you should see 3 + 4 = 7
on the screen. :)
If you see it twice, you can disable the <React.StrictMode>
from index.tsx
that calls the useEffect
block twice.