DioxusLabs / DioxusLabs/dioxus

Dynamically added scripts are always async

Open
#3,757 8 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Rust
Stars
39.1k
Forks
1.9k
Avg merge
4d 10h
Merged PRs (30d)
4

Description

**Problem**

Scripts are not being executed correctly

**Steps To Reproduce**

e.g.

```rust
use dioxus::prelude::*;

fn main() {
dioxus::launch(App);
}

#[component]
fn App() -> Element {
rsx! {
BugExample {}
}
}

#[component]
pub fn BugExample() -> Element {
let code = r#"
use dioxus::prelude::*;

#[component]
pub fn Example() -> Element {}
"#;
use_effect(|| {
// document::eval("hljs.highlightAll();"); // Alternative, also does not work
});
rsx! {
div {
pre {
code { class: "language-rust", {code} }
}
document::Script { {"hljs.highlightAll();"} }
document::Script { src: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/rust.min.js" }
document::Script { src: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" }
document::Link {
href: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css",
rel: "stylesheet",
}
}
}
}
```
Results in
```console
Uncaught ReferenceError: hljs is not defined
at :1:1
at createElementInHead (eval at (quaza_website-0acb08c20af679fe.js:5:25219), :5:254)
at eval (eval at (quaza_website-0acb08c20af679fe.js:5:25219), :6:9)
at eval (eval at (quaza_website-0acb08c20af679fe.js:5:25219), :7:7)
at quaza_website-0acb08c20af679fe.js:5:5396
at handleError (quaza_website-0acb08c20af679fe.js:4:727)
at imports.wbg.__wbg_call_7cccdd69e0791ae2 (quaza_website-0acb08c20af679fe.js:5:5344)
at quaza_website-ab75a3d067b9bc35.wasm.__wbg_call_7cccdd69e0791ae2 externref shim (quaza_website_bg-064fab76afa3a51b.wasm:0x10d100)
at quaza_website-ab75a3d067b9bc35.wasm.js_sys::Function::call1::he541a474704b8a93 (quaza_website_bg-064fab76afa3a51b.wasm:0x104aa8)
at quaza_website-ab75a3d067b9bc35.wasm.::eval::h0df3cb7e03d97a79 (quaza_website_bg-064fab76afa3a51b.wasm:0x1de38)
```
on web. And the formatting is not applied to the code block.

Running
```console
hljs.highlightAll();
```
Directly in the console succeeds and the code block is formatted correctly.

Copying and pasting the html directly from the browser to a new html page and opening succeeds.
```html

quaza_website



hljs.highlightAll();



use dioxus::prelude::*;

#[component]
pub fn Example() -> Element {}



// We can't use a module script here because we need to start the script immediately when streaming
import("/./assets/quaza_website-51efad540bdeaf2e.js").then(
({ default: init }) => {
init("/./assets/quaza_website_bg-53f30410b95b57e0.wasm").then((wasm) => {
if (wasm.__wbindgen_start == undefined) {
wasm.main();
}
});
}
);


/* Inter Font */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap');

#dx-toast-template {
display: none;
visibility: hidden;
}

.dx-toast {
position: absolute;
top: 10px;
right: 0;
padding-right: 10px;
user-select: none;
transition: transform 0.2s ease;
z-index: 2147483647;
}

.dx-toast .dx-toast-inner {
transition: right 0.2s ease-out;
position: fixed;

background-color: #181B20;
color: #ffffff;
font-family: "Inter", sans-serif;

display: grid;
grid-template-columns: auto auto;
min-width: 280px;
min-height: 92px;
width: min-content;
border-radius: 5px;

}

.dx-toast:hover {
cursor: pointer;
transform: translateX(-5px);
}

.dx-toast .dx-toast-level-bar-container {
height: 100%;
width: 6px;
}

.dx-toast .dx-toast-level-bar-container .dx-toast-level-bar {
width: 100%;
height: 100%;
border-radius: 5px 0px 0px 5px;
}

.dx-toast .dx-toast-content {
padding: 13px;
}

.dx-toast .dx-toast-header {
display: flex;
flex-direction: row;
justify-content: start;
align-items: end;
margin-bottom: 13px;
}

.dx-toast .dx-toast-header>svg {
height: 22px;
margin-right: 5px;
}

.dx-toast .dx-toast-header .dx-toast-header-text {
font-size: 16px;
font-weight: 700;
padding: 0;
margin: 0;
}

.dx-toast .dx-toast-msg {
font-size: 14px;
font-weight: 400;
padding: 0;
margin: 0;
}

.dx-toast-level-bar.info {
background-color: #428EFF;
}

.dx-toast-level-bar.success {
background-color: #42FF65;
}

.dx-toast-level-bar.error {
background-color: #FF4242;
}













Your app is being rebuilt.



A non-hot-reloadable change occurred and we must rebuild.




const STORAGE_KEY = "SCHEDULED-DX-TOAST";
let currentToast = null;
let currentTimeout = null;

// Show a toast, removing the previous one.
function showDXToast(headerText, message, progressLevel, durationMs) {
// Close current toast if exists.
closeDXToast();

// Clone template and add unique id.
let toastTemplate = document.getElementById("dx-toast-template");
let cloned = toastTemplate.cloneNode(true);
let toastId = `dx-toast`;
cloned.id = toastId;
currentToast = cloned;

let innerElem = currentToast.querySelector(`#${toastId} .dx-toast-inner`);

// Set the progress level
let progressBarElem = innerElem.querySelector(".dx-toast-inner .dx-toast-level-bar-container .dx-toast-level-bar");
progressBarElem.className = `dx-toast-level-bar ${progressLevel}`;

// Set header text
let headerTextElem = innerElem.querySelector(".dx-toast-inner .dx-toast-header .dx-toast-header-text");
headerTextElem.innerText = headerText;

// Set message
let messageElem = innerElem.querySelector(".dx-toast-inner .dx-toast-msg");
messageElem.innerText = message;

document.body.appendChild(currentToast);

// Add listener to close toasts when clicked.
// Safety: Calling `closeToast` removes the element and all event listeners with it.
currentToast.addEventListener("click", closeDXToast);

// Wait a bit of time so animation plays correctly.
setTimeout(() => {
innerElem.style.right = "0";

currentTimeout = setTimeout(() => {
closeDXToast();
}, durationMs);
}, 100);
}

// Schedule a toast to be displayed after reload.
function scheduleDXToast(headerText, message, level, durationMs) {
let data = {
headerText,
message,
level,
durationMs,
};

let jsonData = JSON.stringify(data);
sessionStorage.setItem(STORAGE_KEY, jsonData);
}

// Close the current toast.
function closeDXToast() {
if (currentToast) {
currentToast.remove();
}
clearTimeout(currentTimeout);
}

// Handle any scheduled toasts after reload.
let potentialData = sessionStorage.getItem(STORAGE_KEY);
if (potentialData) {
sessionStorage.removeItem(STORAGE_KEY);
let data = JSON.parse(potentialData);
showDXToast(data.headerText, data.message, data.level, data.durationMs);
}

```

Thus considering this and looking at the error. This is a Dioxus specific error.

**Expected behavior**

~The formatted code block is displayed~

**Screenshots**

**Environment:**

- Dioxus version: 0.6.2
- Rust version: 1.86.0 nightly
- OS info: NixOS 25.05
- App platform: web

**Edit:**

Actionables from the discussion below
- In rosetta, for a script, define `async` as a compile time error and inform the user that it is always true.
- Since `defer: true` and `async: true` cannot be used together, we should prohibit `defer` as well and advise to use `use_effect` instead
- Document these behaviors

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.