Skip to content

Loading of external scripts fails on browser-refresh but works when hot-reloaded #4071

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
h4ck4l1 opened this issue May 2, 2025 · 2 comments
Labels
bug Something isn't working

Comments

@h4ck4l1
Copy link

h4ck4l1 commented May 2, 2025

Problem
Trying to use wasm_bindgen when using external libraries(Plotly + DataTable), works on hot reload but fails on refreshing the browser

  • when DataTable is used inside the onmounted of table:
  1. The 3rd Party Libraries don't load.
  2. The Css doesn't load.
  3. The dioxus-motion crate also doesn't load.

It becomes a static html page with no css or js.

  • when DataTable is used in the use_effect:
  1. The Css loads correctly
  2. None of the wasm functions or the js loads, including dioxus_motions, plotly, datatables.

I've posted the full example just to show an observation that I have 2 js libraries loading through wasm_bindgen and one works fine but the moment i use the DataTable one i get this error.

  • when datatable is removed altogether
  1. The css loads properly.
  2. Plotly also works properly.
  3. Everything works as intended.

Error stack from console when table_mounted

wasm-bindgen: imported JS function that was not marked as `catch` threw an error: DataTable is not defined

Stack:
ReferenceError: DataTable is not defined
    at http://localhost:8080/assets/plotly_rust-c4b797041e341815.js:5:28247
    at logError (http://localhost:8080/assets/plotly_rust-c4b797041e341815.js:1:21075)
    at imports.wbg.__wbg_newtable_2ddfdc8d28df9a43 (http://localhost:8080/assets/plotly_rust-c4b797041e341815.js:5:28208)
    at plotly_rust-ca6c5624771c5682.wasm.__wbg_newtable_2ddfdc8d28df9a43 externref shim (http://localhost:8080/assets/plotly_rust_bg-a244929460d50db9.wasm:wasm-function[7256]:0x34aee7)
    at plotly_rust-ca6c5624771c5682.wasm.frontend::table_callback::new_table::ha7804c367f7db154 (http://localhost:8080/assets/plotly_rust_bg-a244929460d50db9.wasm:wasm-function[3539]:0x2e5da9)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::events::Callback<Args,Ret>::new::{{closure}}::h2bf88c2c1ebe3fc7 (http://localhost:8080/assets/plotly_rust_bg-a244929460d50db9.wasm:wasm-function[4776]:0x31e5de)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::events::Callback<Args,Ret>::call::h48564f68ca0afd75 (http://localhost:8080/assets/plotly_rust_bg-a244929460d50db9.wasm:wasm-function[2394]:0x28e159)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::events::Callback<Args,Ret>::leak::{{closure}}::h0e23fd7dc3c2a1c3 (http://localhost:8080/assets/plotly_rust_bg-a244929460d50db9.wasm:wasm-function[2158]:0x276baa)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::events::Callback<Args,Ret>::call::h1ee02ae05821753a (http://localhost:8080/assets/plotly_rust_bg-a244929460d50db9.wasm:wasm-function[1920]:0x25c1f3)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::runtime::Runtime::handle_event::h62a54c956afedc76 (http://localhost:8080/assets/plotly_rust_bg-a244929460d50db9.wasm:wasm-function[333]:0x9a5ea)

Uncaught ReferenceError: DataTable is not defined
    at plotly_rust-c4b797041e341815.js:5:28247
    at logError (plotly_rust-c4b797041e341815.js:1:21075)
    at imports.wbg.__wbg_newtable_2ddfdc8d28df9a43 (plotly_rust-c4b797041e341815.js:5:28208)
    at plotly_rust-ca6c5624771c5682.wasm.__wbg_newtable_2ddfdc8d28df9a43 externref shim (plotly_rust_bg-a244929460d50db9.wasm:0x34aee7)
    at plotly_rust-ca6c5624771c5682.wasm.frontend::table_callback::new_table::ha7804c367f7db154 (plotly_rust_bg-a244929460d50db9.wasm:0x2e5da9)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::events::Callback<Args,Ret>::new::{{closure}}::h2bf88c2c1ebe3fc7 (plotly_rust_bg-a244929460d50db9.wasm:0x31e5de)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::events::Callback<Args,Ret>::call::h48564f68ca0afd75 (plotly_rust_bg-a244929460d50db9.wasm:0x28e159)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::events::Callback<Args,Ret>::leak::{{closure}}::h0e23fd7dc3c2a1c3 (plotly_rust_bg-a244929460d50db9.wasm:0x276baa)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::events::Callback<Args,Ret>::call::h1ee02ae05821753a (plotly_rust_bg-a244929460d50db9.wasm:0x25c1f3)
    at plotly_rust-ca6c5624771c5682.wasm.dioxus_core::runtime::Runtime::handle_event::h62a54c956afedc76 (plotly_rust_bg-a244929460d50db9.wasm:0x9a5ea)

Error from console when use_effect

plotly_rust-75a7f9adbcf0ab72.js:1 
 wasm-bindgen: imported JS function that was not marked as `catch` threw an error: DataTable is not defined

Stack:
ReferenceError: DataTable is not defined
    at http://localhost:8080/assets/plotly_rust-75a7f9adbcf0ab72.js:5:28247
    at logError (http://localhost:8080/assets/plotly_rust-75a7f9adbcf0ab72.js:1:21075)
    at imports.wbg.__wbg_newtable_2ddfdc8d28df9a43 (http://localhost:8080/assets/plotly_rust-75a7f9adbcf0ab72.js:5:28208)
    at plotly_rust-732b61d9d92b9c52.wasm.__wbg_newtable_2ddfdc8d28df9a43 externref shim (http://localhost:8080/assets/plotly_rust_bg-b1dcbd201d54342e.wasm:wasm-function[7253]:0x34adcc)
    at plotly_rust-732b61d9d92b9c52.wasm.frontend::table_callback::new_table::h14f91bfa85cc1431 (http://localhost:8080/assets/plotly_rust_bg-b1dcbd201d54342e.wasm:wasm-function[3537]:0x2e5c4c)
    at plotly_rust-732b61d9d92b9c52.wasm.dioxus_core::events::Callback<Args,Ret>::new::{{closure}}::hb74eb1de67f260ec (http://localhost:8080/assets/plotly_rust_bg-b1dcbd201d54342e.wasm:wasm-function[6693]:0x345f01)
    at plotly_rust-732b61d9d92b9c52.wasm.dioxus_core::events::Callback<Args,Ret>::call::hbab0d54ba25163e4 (http://localhost:8080/assets/plotly_rust_bg-b1dcbd201d54342e.wasm:wasm-function[2108]:0x27165b)
    at plotly_rust-732b61d9d92b9c52.wasm.<dioxus_core::events::Callback<Args,Ret> as core::ops::deref::Deref>::deref::{{closure}}::ha3e91b648e61af6a (http://localhost:8080/assets/plotly_rust_bg-b1dcbd201d54342e.wasm:wasm-function[8385]:0x3500f6)
    at plotly_rust-732b61d9d92b9c52.wasm.dioxus_core::reactive_context::ReactiveContext::reset_and_run_in::h7c5337dfa9ab92f3 (http://localhost:8080/assets/plotly_rust_bg-b1dcbd201d54342e.wasm:wasm-function[3028]:0x2c261f)
    at plotly_rust-732b61d9d92b9c52.wasm.core::ops::function::FnOnce::call_once{{vtable.shim}}::h141ebb59106be764 (http://localhost:8080/assets/plotly_rust_bg-b1dcbd201d54342e.wasm:wasm-function[6246]:0x33fc9a)
plotly_rust-75a7f9adbcf0ab72.js:4 
 Uncaught ReferenceError: DataTable is not defined
    at plotly_rust-75a7f9adbcf0ab72.js:5:28247
    at logError (plotly_rust-75a7f9adbcf0ab72.js:1:21075)
    at imports.wbg.__wbg_newtable_2ddfdc8d28df9a43 (plotly_rust-75a7f9adbcf0ab72.js:5:28208)
    at plotly_rust-732b61d9d92b9c52.wasm.__wbg_newtable_2ddfdc8d28df9a43 externref shim (plotly_rust_bg-b1dcb…4342e.wasm:0x34adcc)
    at plotly_rust-732b61d9d92b9c52.wasm.frontend::table_callback::new_table::h14f91bfa85cc1431 (plotly_rust_bg-b1dcb…4342e.wasm:0x2e5c4c)
    at plotly_rust-732b61d9d92b9c52.wasm.dioxus_core::events::Callback<Args,Ret>::new::{{closure}}::hb74eb1de67f260ec (plotly_rust_bg-b1dcb…4342e.wasm:0x345f01)
    at plotly_rust-732b61d9d92b9c52.wasm.dioxus_core::events::Callback<Args,Ret>::call::hbab0d54ba25163e4 (plotly_rust_bg-b1dcb…4342e.wasm:0x27165b)
    at plotly_rust-732b61d9d92b9c52.wasm.<dioxus_core::events::Callback<Args,Ret> as core::ops::deref::Deref>::deref::{{closure}}::ha3e91b648e61af6a (plotly_rust_bg-b1dcb…4342e.wasm:0x3500f6)
    at plotly_rust-732b61d9d92b9c52.wasm.dioxus_core::reactive_context::ReactiveContext::reset_and_run_in::h7c5337dfa9ab92f3 (plotly_rust_bg-b1dcb…4342e.wasm:0x2c261f)
    at plotly_rust-732b61d9d92b9c52.wasm.core::ops::function::FnOnce::call_once{{vtable.shim}}::h141ebb59106be764 (plotly_rust_bg-b1dcb…4342e.wasm:0x33fc9a)
plotly_rust_bg-b1dcb…4342e.wasm:0x3512ce 
 Uncaught RuntimeError: unreachable
    at plotly_rust-732b61d9d92b9c52.wasm.__rustc[2cdc4cefc7961cb7]::__rust_start_panic (plotly_rust_bg-b1dcb…4342e.wasm:0x3512ce)
    at plotly_rust-732b61d9d92b9c52.wasm.__rustc[2cdc4cefc7961cb7]::rust_panic (plotly_rust_bg-b1dcb…4342e.wasm:0x34b8e5)
    at plotly_rust-732b61d9d92b9c52.wasm.std::panicking::rust_panic_with_hook::hba45e0c8b791d4c9 (plotly_rust_bg-b1dcb…4342e.wasm:0x2f3fed)
    at plotly_rust-732b61d9d92b9c52.wasm.std::panicking::begin_panic_handler::{{closure}}::h126584d154d05a2f (plotly_rust_bg-b1dcb…4342e.wasm:0x30fc27)
    at plotly_rust-732b61d9d92b9c52.wasm.std::sys::backtrace::__rust_end_short_backtrace::h58104e981bb12318 (plotly_rust_bg-b1dcb…4342e.wasm:0x3508ed)
    at plotly_rust-732b61d9d92b9c52.wasm.__rustc[2cdc4cefc7961cb7]::rust_begin_unwind (plotly_rust_bg-b1dcb…4342e.wasm:0x3461d8)
    at plotly_rust-732b61d9d92b9c52.wasm.core::panicking::panic_fmt::h6ec6dd4857015a2e (plotly_rust_bg-b1dcb…4342e.wasm:0x346204)
    at plotly_rust-732b61d9d92b9c52.wasm.core::cell::panic_already_borrowed::hfe7b7f9f80748e17 (plotly_rust_bg-b1dcb…4342e.wasm:0x334e39)
    at plotly_rust-732b61d9d92b9c52.wasm.wasm_bindgen_futures::task::singlethread::Task::run::h72b7fb50a6b40441 (plotly_rust_bg-b1dcb…4342e.wasm:0x2e6a65)
    at plotly_rust-732b61d9d92b9c52.wasm.wasm_bindgen_futures::queue::QueueState::run_all::h90b04ef9abdbc81b (plotly_rust_bg-b1dcb…4342e.wasm:0x27e71d)
dataTables.js:41 
 Uncaught ReferenceError: jQuery is not defined
    at dataTables.js:41:31
    at dataTables.js:43:2

// web_page.rs

use std::{any::Any, time::Duration};
use dioxus::prelude::*;
use dioxus_motion::{prelude::*, use_motion, AnimationManager};
use itertools::Itertools;
use plotly::{ common::{color::Rgb, Font, Marker, Mode, Pad}, layout::{themes::PLOTLY_DARK, update_menu::{Button, UpdateMenu}, Axis}, plot::Traces, Histogram, Layout, Plot, Scatter};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use web_sys::js_sys::Math;
use crate::{table_callback::new_table, CubeSpinner, Markdown, MarkdownComponent, Route, CUSTOM_LAYOUT};

use super::get_histogram;
const MUSHROOM_FIRST_CAT_COL_MARKDOWN: &str = include_str!("mushroom_markdowns/mushroom_first_cat_col_markdown.md");

static MUSHROOM_CAP_DIA_IMAGE: Asset = asset!("src/mushroom/mushroom_assets/cap_diameter.png");

#[component]
pub fn MushroomFirstCategoricalColumn() -> Element {
    let mut is_hidden = use_signal(|| true);
    let div_id = use_signal(|| "mushroom-plot");
    let table_div_id = use_signal(|| "mushroom-cap-dia-table");
    let mut error_response = use_signal(|| "".to_string());
    let mut scale_value = use_motion(1f32);
    let table_rows = use_signal(|| vec![
        ("Frist_Name_1","Second_Name_1",25),
        ("First_Name_2","Second_Name_2",22),
        ("First_Name_3", "Second_Name_3",21)
    ]);


    use_effect(move || {
        let mut is_hidden = is_hidden.clone();
        spawn(async move {
            match mushroom_first_cat_col_data_request().await {
                Ok(plot) => {
                    is_hidden.set(false);
                    async_std::task::sleep(Duration::from_millis(500)).await;
                    if !is_hidden() {
                        let _ = plotly::bindings::new_plot(div_id(), &plot).await;
                    }
                },
                Err(err) => {
                    error_response.set(err.to_string());
                }
            }
        });
    });

    let table_mount = move |_| {
        new_table(table_div_id());
    };


    let mouse_enter_scaleup = move |_| {
        scale_value.animate_to(1.2, AnimationConfig::new(
            AnimationMode::Spring(
                Spring::default()
            )
        ));
    };

    let mouse_leave_scaledown = move |_| {
        scale_value.animate_to(1.0, AnimationConfig::new(
            AnimationMode::Spring(
                Spring::default()
            )
        ));
    };
    

    rsx!{
        div {
            class: "heading-container", 
            h1 {
                class: "heading",
                color: "cyan", 
                "Mushroom Cap Diameter Plot"
            }
        }
        div {
            class: "asset-image-container",  
            img {
                class:"asset-image",
                onmouseenter: mouse_enter_scaleup,
                onmouseleave: mouse_leave_scaledown,
                style: "transform: scale({scale_value.get_value()})",
                src: MUSHROOM_CAP_DIA_IMAGE
            }
        }
        if is_hidden() {
            div {
                class: "cube-spinner",
                CubeSpinner {  }
            }
        } else {
            div {  
                class: "graph-container",
                div {  
                    id: "{div_id()}",
                    class: "graph-class"
                }
            }
        }
        div {  
            "{error_response()}"
        }
        div {
            class: "general-heading-container",
            h1 {  
                class: "general-heading",
                "mushroom cap diameter observations"
            }
        }
        MarkdownComponent { text: MUSHROOM_FIRST_CAT_COL_MARKDOWN}
        div {
            table {
                onmounted: table_mount,
                id: "{table_div_id()}",
                class: "display",
                thead {  
                    tr {  
                        th { "Name Col" }
                        th { "Age Col" }
                        th { "Place Col" }
                    }
                }
                tbody {
                    id: "table-element",
                    for (i,(first_name, last_name, age)) in table_rows().iter().enumerate() {
                        tr {
                            td { border: "2px solid cyan","{first_name}" }
                            td { border: "2px solid cyan","{last_name}" }
                            td { border: "2px solid cyan","{age}" }
                        }
                    }
                }
            }
        }
    }
}


async fn mushroom_first_cat_col_data_request() -> Result<Plot,anyhow::Error> {
    
    // making the plot
    Ok(plot)
}
// table_callback.rs

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {

    #[wasm_bindgen(js_name=DataTable)]
    type DataTable;

    #[wasm_bindgen(constructor)]
    fn new_table_(div_id:&str) -> DataTable;
}

pub fn new_table(div_id:&str) {

    let table = DataTable::new_table_(&format!("#{}",div_id));
}

Expected behavior

  • Refreshing should load the external scripts after mounting.

Screenshots

expected:

20250502-1623-32.4563536.mp4

currently happening:

20250502-1626-32.5720359.mp4

Environment:

  • Dioxus version: v0.6.3
  • Rust version: rustc 1.88.0-nightly (17ffbc81a 2025-04-04)
  • OS info: WSL Ubuntu
  • App platform: Web

Questionnaire

I am actually interested in solving this myself, I need this solved to implement so many 3rd party libraries that are currently not available in dioxus to apply it in my dashboard app

I think the script is not being loaded, but I don't know whether this is wasm-bindgen problem or a dioxus general problem which has already been solved. because plotly which is also importing functions from js into rs using bindgen is working as expected. even with refresh.

Thankyou

@h4ck4l1 h4ck4l1 added the bug Something isn't working label May 2, 2025
@h4ck4l1
Copy link
Author

h4ck4l1 commented May 3, 2025

Ok i solved this injecting scripts just before mounting and that took a ton of time, but it will be helpful for loading 3rd party scripts

use js_sys::Promise;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::JsFuture;
use web_sys::{window, HtmlScriptElement};
#[wasm_bindgen]
extern "C" {

    #[wasm_bindgen(js_name=DataTable)]
    type DataTable;

    #[wasm_bindgen(constructor)]
    pub fn new_table_(div_id: &str) -> DataTable;
}

pub async fn new_table(div_id: &str) -> Result<(),JsValue> {

    JsFuture::from(load_script("https://code.jquery.com/jquery-3.7.1.js")).await?;
    JsFuture::from(load_script("https://cdn.datatables.net/2.3.0/js/dataTables.js")).await?;

    let _ = DataTable::new_table_(&format!("#{}",div_id));

    Ok(())

}

fn load_script(src: &str) -> Promise {
    let doc = window().unwrap().document().unwrap();
    let script = doc
        .create_element("script").unwrap()
        .dyn_into::<HtmlScriptElement>().unwrap();

    script.set_src(src);
    script.set_type("text/javascript");

    let promise = Promise::new(&mut |resolve, reject| {
        let onload = Closure::once_into_js(move || {
            resolve.call0(&JsValue::NULL).unwrap();
        });
        let onerror = Closure::once_into_js(move || {
            reject.call0(&JsValue::NULL).unwrap();
        });
        script.set_onload(Some(onload.unchecked_ref()));
        script.set_onerror(Some(onerror.unchecked_ref()));
    });

    doc.head().unwrap()
        .append_child(&script).unwrap();
    promise
}


#![allow(unused,non_snake_case)]
use std::time::Duration;
use dioxus::prelude::*;
use crate::{table_callbacks::new_table, Route};
pub fn TablePage() -> Element {
    let div_id = use_signal(|| "table-id".to_string());
    let mut is_loaded = use_signal(|| false);
    let table_rows = use_signal(|| vec![
        ("First Name", 21, 55),
        ("Second Name", 22, 60),
        ("Third Name", 25, 66)
    ]);
    let nav = navigator();
    use_effect(move || {
        let mut is_loaded = is_loaded.clone();
        spawn(async move {
            if is_loaded() {
                let _ = new_table(&div_id()).await;
            }
        });
    });
    rsx! {
        div {  
            h2 {  
                onclick: move |e| {
                    e.prevent_default();
                    nav.push(Route::HomePage {  });
                },
                "Go Back"
            }
        }
        div {  
            h1 {  
                "This is Table Page"
            }
        }
        div {
            onmounted: move |e| {
                e.prevent_default();
                is_loaded.set(true);
            },
            table {
                id: "{div_id()}",
                class: "display",
                thead {  
                    tr {  
                        th { "Name" }
                        th { "Age" }
                        th { "Height" }
                    }
                }
                tbody {
                    for (name,age,w) in table_rows() {
                        tr {  
                            td { "{name}"  }
                            td { "{age}"  }
                            td { "{w}"  }
                        }
                    }
                }         
            }
        }
    }
}


but before i close this i would like to ask @ealmloff whether if there is a dioxus-y way to do inject scripts before mounting elements

If there is no dioxus-y way to do this can we have this incorporated into dioxus in someway please, I went through a bunch of comments in rust subreddit on a dioxus post and most people are hesitant to shift frameworks is because of date-pickers, tables and stuff, creating wasm-bindgen bridges for the external js functions is very easy but ensuring scripts loading on time is the one thing that difficult to get ahold of.

Thankyou.

@ealmloff
Copy link
Member

ealmloff commented May 5, 2025

Are you importing the files inside of wasm bindgen or just the items? If you are importing the files, this might be a caching issue which should be fixed by #3988

If not, you can use the Link component to add a link to the document head to load your asset

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants