Skip to content

Island's child component's reactivity doesn't work #4476

@cgomlobo

Description

@cgomlobo

Describe the bug
When creating a simple component with a button that increments a counter (the tipical basic example) and render it as a child of an island component, the reactivity doesn't work and the counter is not updated.

Leptos Dependencies

leptos = { version = "0.8.0" }
leptos_router = { version = "0.8.0" }
axum = { version = "0.8.0", optional = true }
console_error_panic_hook = { version = "0.1", optional = true }
leptos_axum = { version = "0.8.0", optional = true }
leptos_meta = { version = "0.8.0" }
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
wasm-bindgen = { version = "=0.2.105" }
web-sys = { version = "0.3.82" }

To Reproduce
Steps to reproduce the behavior:

  1. Create a Leptos project using axum with a SSG configuration:
#[cfg(feature = "ssr")]
#[tokio::main]
async fn main() {
  use axum::Router;
  use id_card_obfuscator_axum::app::*;
  use leptos::{logging::log, prelude::*};
  use leptos_axum::{generate_route_list_with_ssg, LeptosRoutes};

  let conf = get_configuration(None).unwrap();
  let addr = conf.leptos_options.site_addr;
  let leptos_options = conf.leptos_options;
  // Generate the list of routes in your Leptos App
  let (routes, static_routes) = generate_route_list_with_ssg({
      use id_card_obfuscator_axum::app::shell;

      let leptos_options = leptos_options.clone();
      move || shell(leptos_options.clone())
  });

  static_routes.generate(&leptos_options).await;

  let app = Router::new()
      .leptos_routes(&leptos_options, routes, {
          let leptos_options = leptos_options.clone();
          move || shell(leptos_options.clone())
      })
      .fallback(leptos_axum::file_and_error_handler(shell))
      .with_state(leptos_options);

  // run our app with hyper
  // `axum::Server` is a re-export of `hyper::Server`
  log!("listening on http://{}", &addr);
  let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
  axum::serve(listener, app.into_make_service())
      .await
      .unwrap();
  1. Set up hydratation to support islands
#[cfg(feature = "hydrate")]
#[wasm_bindgen::prelude::wasm_bindgen]
pub fn hydrate() {
  console_error_panic_hook::set_once();
  leptos::mount::hydrate_islands();
}
  1. Create an island component with a simple auto-increment button that contains another child component with another auto-increment button.
pub fn shell(options: LeptosOptions) -> impl IntoView {
  view! {
      <!DOCTYPE html>
      <html lang="en">
          <head>
              <meta charset="utf-8"/>
              <meta name="viewport" content="width=device-width, initial-scale=1"/>
              <AutoReload options=options.clone()/>
              <HydrationScripts options islands=true/>
              <MetaTags />
          </head>
          <body>
              <App/>
          </body>
      </html>
  }
}

#[component]
pub fn App() -> impl IntoView {
  view! {
      <Title text="Welcome to Leptos"/>

      <Parent >
          <Child />
      </Parent>
  }
}

#[island]
pub fn Parent(children: Children) -> impl IntoView {
  let count = RwSignal::new(0);

  view! {
      {children()}
      <button on:click=move |_| *count.write() += 1>Parent +1: {count}</button>
  }
}

#[component]
pub fn Child() -> impl IntoView {
  let count = RwSignal::new(0);
  view! {
      <button on:click=move |_| *count.write() += 1>Child +1: {count}</button>
  }
}
  1. Build the project running cargo leptos watch.
  2. Click both buttons and observe that only the parent one works.

Screenshots

Grabacion.de.pantalla.desde.2025-12-08.00-49-16.webm

Next Steps

  • I will make a PR
  • I would like to make a PR, but need help getting started
  • I want someone else to take the time to fix this
  • This is a low priority for me and is just shared for your information

Additional context
N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions