diff --git a/Cargo.lock b/Cargo.lock
index 26bfbea..bfe3995 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -68,6 +68,8 @@ name = "react"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
+ "js-sys",
+ "log",
"shared",
"wasm-bindgen",
"wasm-bindgen-test",
diff --git a/examples/hello-world/src/main.tsx b/examples/hello-world/src/main.tsx
index cdf3f95..78a90af 100644
--- a/examples/hello-world/src/main.tsx
+++ b/examples/hello-world/src/main.tsx
@@ -1,5 +1,6 @@
import {createRoot} from 'react-dom'
+
const comp =
hello world
console.log(comp)
console.log(createRoot(document.getElementById("root")))
diff --git a/packages/react/Cargo.toml b/packages/react/Cargo.toml
index e2e2cfc..225b9c8 100644
--- a/packages/react/Cargo.toml
+++ b/packages/react/Cargo.toml
@@ -19,7 +19,9 @@ shared = { path = "../shared" }
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
-web-sys = { version = "0.3.69", features = ["console"] }
+web-sys = { version = "0.3.69", features = ["console"] }
+js-sys = "0.3.69"
+log = "0.4.21"
[dev-dependencies]
wasm-bindgen-test = "0.3.34"
diff --git a/packages/react/src/lib.rs b/packages/react/src/lib.rs
index 9c4be9a..03d41f8 100644
--- a/packages/react/src/lib.rs
+++ b/packages/react/src/lib.rs
@@ -1,6 +1,36 @@
+use js_sys::{Object, Reflect};
use wasm_bindgen::prelude::*;
-#[wasm_bindgen]
-pub fn jsxDEV() -> String {
- "hello world".to_string()
-}
\ No newline at end of file
+use shared::REACT_ELEMENT_TYPE;
+
+#[wasm_bindgen(js_name = jsxDEV)]
+pub fn jsx_dev(_type: &JsValue, config: &JsValue, key: &JsValue) -> JsValue {
+ let react_element = Object::new();
+ Reflect::set(
+ &react_element,
+ &"&&typeof".into(),
+ &JsValue::from_str(REACT_ELEMENT_TYPE),
+ )
+ .expect("$$typeof panic");
+ Reflect::set(&react_element, &"type".into(), _type).expect("_type panic");
+ Reflect::set(&react_element, &"key".into(), key).expect("key panic");
+
+ let conf = config.dyn_ref::