Giter Club home page Giter Club logo

dioxus's Introduction



Build for web, desktop, and mobile, and more with a single codebase. Zero-config setup, integrated hotreloading, and signals-based state management. Add backend functionality with Server Functions and bundle with our CLI.

fn app() -> Element {
    let mut count = use_signal(|| 0);

    rsx! {
        h1 { "High-Five counter: {count}" }
        button { onclick: move |_| count += 1, "Up high!" }
        button { onclick: move |_| count -= 1, "Down low!" }
    }
}

⭐️ Unique features:

  • Cross-platform apps in three lines of code (web, desktop, mobile, server, and more)
  • Ergonomic state management combines the best of React, Solid, and Svelte
  • Extremely performant, powered by Rust's fastest wasm-framework sledgehammer
  • Integrated bundler for deploying to the web, macOS, Linux, and Windows
  • And more! Read the take a tour of Dioxus.

Instant hot-reloading

With one command, dx serve and your app is running. Edit your markup and styles and see the results in real time. Rust code hotreloading is not yet 1st class, but possible with hot-lib-reloader.

Bundler for deploying to the web and desktop

Simply run dx bundle and your app will be built and bundled with maximization optimizations. On the web, take advantage of .avif generation, .wasm compression, minification, and more. Build webapps weighing less than 50kb and desktop/mobile apps less than 15mb.

Fantastic documentation

We've put a ton of effort into building clean, readable, and comprehensive documentation. All html elements and listeners are documented with MDN docs, and our docsite runs continuous integration with Dioxus itself to ensure that the docs are always up to date. Check out the Dioxus website for guides, references, recipes, and more. Fun fact: we use the Dioxus website as a testbed for new diouxs features - check it out!

Emphasis on developer experience

Dioxus prioritizes developer experience, and we've put a ton of effort into end-to-end tooling. We've built a VSCode extension that autoformats your RSX code, converts HTML to RSX, and more. We've also built a very powerful CLI that supports creating new apps, serving them, and cross-platform bundling, with deployment on the roadmap.

Community

Dioxus is a community-driven project, with a very active Discord and GitHub community. We're always looking for help, and we're happy to answer questions and help you get started. Our SDK is community-run and we even have a GitHub organization for the best Dioxus crates that receive free upgrades and support.

Full-time core team

Dioxus has grown from a side project to a small team of fulltime engineers. Thanks to the generous support of FutureWei, Satellite.im, the GitHub Accelerator program, we're able to work on Dioxus full-time. Our long term goal is for Dioxus to become self-sustaining by providing paid high-quality enterprise tools. If your company is interested in adopting Dioxus and would like to work with us, please reach out!

Supported Platforms

Web
Tier 1 Support
  • Render directly to the DOM using WebAssembly
  • Pre-render with SSR and rehydrate on the client
  • Simple "hello world" at about 50kb, comparable to React
  • Built-in dev server and hot reloading for quick iteration
Fullstack
Tier 1 Support
  • Suspense, hydration, and server-side rendering
  • Quickly drop in backend functionality with server functions
  • Extractors, middleware, and routing integrations
  • Compatible with desktop and mobile!
Desktop
Tier 1 Support
  • Render using Webview or - experimentally - with WGPU or Freya (skia)
  • Zero-config setup. Simply `cargo run` or `dx serve` to build your app
  • Full support for native system access without IPC
  • Supports macOS, Linux, and Windows. Portable <3mb binaries
Liveview
Tier 1 Support
  • Render apps - or just a single component - entirely on the server
  • Integrations with popular Rust frameworks like Axum and Warp
  • Extremely low-latency and ability to support 10,000+ simultaneous apps
Mobile
Tier 2 Support
  • Render using Webview or - experimentally - with WGPU or Skia
  • Support for iOS and Android
  • Currently quite experimental, with lots of improvements coming throughout 2024
Terminal
Tier 2 Support
  • Render apps directly into your terminal, similar to ink.js
  • Powered by the familiar flexbox and CSS model of the browser
  • Built-in widgets like text input, buttons, and focus system

Running the examples

The examples in the top level of this repository can be run with cargo run --example <example>. However, we encourage you to download the dioxus-cli and run the examples with dx serve since many examples also support web. When running for web, you either need to modify the Cargo.toml to disable the default desktop feature, or use

Dioxus vs other frameworks

We love all frameworks and enjoy watching innovation in the Rust ecosystem. In fact, many of our projects are shared with other frameworks. For example, our flex-box library Taffy is used by Bevy, Zed, Lapce, Iced, and many more.

Dioxus places an emphasis on a few key points that make it different from other frameworks:

  • React-like: we rely on concepts like components, props, and hooks to build UIs, with our state management being closer to Svelte than to SolidJS.
  • HTML and CSS: we lean completely into HTML and CSS, quirks and all.
  • Renderer-agnostic: you can swap out the renderer for any platform you want thanks to our fast VirtualDOM.
  • Collaborative: whenever possible, we spin out crates like Taffy, magnanis, include_mdbook, and blitz so the ecosystem can grow together.

Dioxus vs Tauri

Tauri is a framework for building desktop (and soon, mobile) apps where your frontend is written in a web-based framework like React, Vue, Svelte, etc. Whenever you need to do native work, you can write Rust functions and call them from your frontend.

  • Natively Rust: Tauri's architecture limits your UI to either JavaScript or WebAssembly. With Dioxus, your Rust code is running natively on the user's machine, letting you do things like spawning threads, accessing the filesystem, without any IPC bridge. This drastically simplifies your app's architecture and makes it easier to build. You can build a Tauri app with Dioxus-Web as a frontend if you'd like.

  • Different scopes: Tauri needs to support JavaScript and its complex build tooling, limiting the scope of what you can do with it. Since Dioxus is exclusively focused on Rust, we're able to provide extra utilities like Server Functions, advanced bundling, and a native renderer.

  • Shared DNA: While Tauri and Dioxus are separate projects, they do share libraries like Tao and Wry: windowing and webview libraries maintained by the Tauri team.

Dioxus vs Leptos

Leptos is a library for building fullstack web-apps, similar to SolidJS and SolidStart. The two libraries share similar goals on the web, but have several key differences:

  • Reactivity model: Leptos uses signals for its underlying reactivity, while Dioxus opts for a VirtualDom and re-renders. While in theory signals are more efficient, in practice, Dioxus' VirtualDom performs little-to-no actual diffing (thanks to our block-dom inspired templates) and is actually faster than Leptos.

  • Control flow: Because Leptos uses signals for reactivity, you are constrained to Leptos' primitives for things like for loops and if statements. If you get this wrong, your app will lose reactivity, leading to hard to debug UI issues. With Dioxus, you can use iterators, regular Rust for loops and if statements, and your app will still be reactive. In practice, a Dioxus component to insert counters into a list might look like this:

fn Counters() -> Element {
    let mut counters = use_signal(|| vec![0; 10]);

    rsx! {
        button { onclick: move |_| counters.push(counters.len()), "Add Counter" }
        ul {
            for idx in 0..counters.len() {
                li {
                    button { onclick: move |_| counters.write()[idx] += 1, "{counters.index(idx)}" }
                    button { onclick: move |_| { counters.remove(idx); }, "Remove" }
                }
            }
        }
    }
}

While in Leptos you would use the <For> component.:

fn Counters() -> impl IntoView {
    let counters = RwSignal::new(vec![0; 10]);

    view! {
        <button on:click=move |_| counters.update(|n| n.push(n.len()))>"Add Counter"</button>
        <For
            each=move || 0..counters.with(Vec::len)
            key=|idx| *idx
            let:idx
        >
            <li>
                <button on:click=move |_| counters.update(|n| n[idx] += 1)>
                    {Memo::new(move |_| counters.with(|n| n[idx]))}
                </button>
                <button on:click=move |_| counters.update(|n| { n.remove(idx); })>
                    "Remove"
                </button>
            </li>
        </For>
    }
}
  • Copy state: Dioxus 0.1 to 0.4 relied on lifetimes to relax the rules of Rust's borrow checker. This worked well for event handlers, but struggled around async. In Dioxus 0.5, we've switched to a Copy state model borrowed from Leptos.

  • Different scopes: Dioxus provides renderers for web, desktop, mobile, LiveView, and more. We also maintain community libraries and a cross-platform SDK. The scope of this work is huge, meaning we've historically released at a slower cadence than Leptos. Leptos focuses on the fullstack web, with features that Dioxus doesn't have like <Suspense />-based streaming HTML, islands, <Form /> components, and other web-specific features. Generally, web apps you build with Leptos will have a smaller footprint.

  • Different DSLs: While both frameworks target the web, Dioxus uses its own custom Rust-like DSL for building UIs while Leptos uses a more HTML-like syntax. We chose this to retain compatibility with IDE features like codefolding and syntax highlighting. Generally, Dioxus leans into more "magic" with its DSL. For example, dioxus will automatically format strings for you while Leptos can split up strings into static and dynamic segments.

// dioxus
rsx! {
  div { class: "my-class", enabled: true, "Hello, {name}" }
}

// leptos
view! {
  <div class="my-class" enabled={true}>
    "Hello "
    {name}
  </div>
}

Dioxus vs Yew

Yew is a framework for building single-page web apps and initially served as an inspiration for Dioxus. Unfortunately, the architecture of Yew didn't support the various features we wanted, and thus Dioxus was born.

  • Single-page apps: Yew is designed exclusively for single-page web apps and is instrinsically tied to the web platform. Dioxus is fullstack and crossplatform, making it suitable for building web, desktop, mobile, and server apps.

  • Developer Tooling: Dioxus provides a number of utilities like autoformatting, hotreloading, and a bundler.

  • Ongoing support: Dioxus is very actively maintained with new features and bug fixes being added on a daily basis.

Dioxus vs egui

egui is a cross-platform GUI library for Rust powering tools like Rerun.io.

  • Immediate vs Retained: egui is designed to be re-rendered on every frame. This is suitable for games and other interactive applications, but it does not retain style and layout state between frames. Dioxus is a retained UI framework, meaning that the UI is built once and then modified between frames. This enables Dioxus to use native web technologies like HTML and CSS with better battery life and performance.

  • Customizable: egui brings its own styling and layout solution while Dioxus expects you to use the built-in HTML and CSS. This enables dioxus apps to use any CSS library like Tailwind or Material UI.

  • State management: egui's state management is based on a single global state object. Dioxus encourages encapsulation of state by using components and props, making components more reusable.

Dioxus vs Iced

Iced is a cross-platform GUI library inspired by Elm. Iced renders natively with WGPU and supports the web using DOM nodes.

  • Elm state management: Iced uses Elm's state management model, which is based on message passing and reducers. This is simply a different state management model than Dioxus and can be rather verbose at times.

  • Native Feel: Since Dioxus uses a webview as its renderer, it automatically gets native text input, paste handling, and other native features like accessibility. Iced's renderer currently doesn't implement these features, making it feel less native.

  • WGPU: Dioxus' WGPU renderer is currently quite immature and not yet reader for production use. Iced's WGPU renderer is much more mature and is being used in production. This enables certain types of apps that need GPU access to be built with Iced that can't currently be built with Dioxus.

Dioxus vs Electron

Dioxus and Electron are two entirely different projects with similar goals. Electron makes it possible for developers to build cross-platform desktop apps using web technologies like HTML, CSS, and JavaScript.

  • Lightweight: Dioxus uses the system's native WebView - or optionally, a WGPU renderer - to render the UI. This makes a typical Dioxus app about 15mb on macOS in comparison to Electron's 100mb. Electron also ships an embedded chromium instance which cannot share system resources with the host OS in the same way as Dioxus.

  • Maturity: Electron is a mature project with a large community and a lot of tooling. Dioxus is still quite young in comparison to Electron. Expect to run into features like deeplinking that require extra work to implement.

Contributing

License

This project is licensed under the MIT license.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Dioxus by you, shall be licensed as MIT, without any additional terms or conditions.

dioxus's People

Contributors

andrew15-5 avatar asaaki avatar autarch avatar bunnybites avatar dangerise avatar dependabot[bot] avatar dogedark avatar ealmloff avatar egegungordu avatar esimkowitz avatar eventualbuddha avatar exotik850 avatar flisky avatar jkelleyrtp avatar kdwarn avatar maccesch avatar marc2332 avatar mrxiaozhuox avatar nicoburns avatar niedzwiedzw avatar oovm avatar overlisting avatar pascalbehmenburg avatar rmazeiks avatar serzhiio avatar t1m0t avatar tefiledo avatar tigerros avatar wiggles-dev avatar xtekc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dioxus's Issues

Disable reload context menu

Running a basic "Hello World" app in Linux I notices a bunch of strange stuff going on:

  • Multiple-second load times for the content after the window is initialized (might be inherent to platform, not sure if can be fixed)
  • Weird menus: App has two menus in the menubar: "First menu" and "Second menu". First menu gives a number of options like "About App", "Quit", etc., but they do nothing. Second menu creates a strange blank menu that has low width and big height.
  • Right-clicking in the window shows a menu with greyed out "Forward", "Stop", and "Backward", as well as working "Reload" and "Inspect Element". Hitting reload breaks the app.

The menus might be intended, but reload breaking stuff is clearly not.

isn't this a dangling pointer?

#[allow(clippy::mut_from_ref)]
pub fn use_hook<'src, State: 'static>(
&'src self,
initializer: impl FnOnce(usize) -> State,
) -> &'src mut State {
let mut vals = self.hook_vals.borrow_mut();
let hook_len = vals.len();
let cur_idx = self.hook_idx.get();
if cur_idx >= hook_len {
vals.push(self.hook_arena.alloc(initializer(hook_len)));
}
vals
.get(cur_idx)
.and_then(|inn| {
self.hook_idx.set(cur_idx + 1);
let raw_box = unsafe { &mut **inn };
raw_box.downcast_mut::<State>()
})
.expect(
r###"
Unable to retrieve the hook that was initialized at this index.
Consult the `rules of hooks` to understand how to use hooks properly.
You likely used the hook in a conditional. Hooks rely on consistent ordering between renders.
Functions prefixed with "use" should never be called conditionally.
"###,
)
}

[feature request] - Hot Module Replacement

Hey,
was trying out Dioxus. looks excellet so far really well done 👍

was thinking is there any way dioxus support HMR? tools like tauri
rely on other dev server to provide updated code immediately
but not sure if same can be achieved with dioxus? since on every
change closing app and reopening is a bit tedious!

File drag and drop support

Thank you very much for making such a wonderful crate.

Does dioxus support <input type="file">?

From what little research I've done, dioxus-desktop and others don't seem to support it.


My idea is to handle wry::WebViewBuilder::with_file_drop_handler properly and create dioxus own events to handle it.

`prevent_default` cannot take effect

a {
    role: "button",
    class: "navbar-item",
    href: "/",
    "aria-label": "menu",
    "aria-expanded": "false",
    "data-target": "navbarMainMenu",
    prevent_default: "onclick",
    onclick: move |_| {cl.set(!cl)},
    img {
        src: "https://bulma.io/images/bulma-logo.png",
        width: "112",
        height: "28"
    }
}

when the img onclick, will redirect, the prevent_default is not take effect.

from: Discord Discussion

runtime `BorrowMut` error

Package related : web
Context: runtime

I have a runtime error stating that cx.consume_context::<RouterService>() is already borrowed.
I know where in my code it has been borrowed but how to release and avoid this runtime error?

It happens in this piece of code:

onclick: move |_| {
    cx.consume_context::<RouterService>().as_ref().unwrap().push_route("/")
}

I'm using consume_context in another component of my app so I understand the error but how avoid this already borrowed runtime error?

Attempting to install and compile `dioxus-cli` crashes

I receive the following errors when I try and install this cli tooling for dioxus via cargo install dioxus-cli:

   Compiling dioxus-cli v0.1.0
error[E0599]: no function or associated item named `new_immediate` found for trait object `dyn notify::Watcher` in the current scope
  --> /home/ed/.cargo/registry/src/github.com-1ecc6299db9ec823/dioxus-cli-0.1.0/src/develop.rs:43:52
   |
43 |     let mut watcher: RecommendedWatcher = Watcher::new_immediate(move |res| {
   |                                                    ^^^^^^^^^^^^^ function or associated item not found in `dyn notify::Watcher`

error[E0308]: mismatched types
  --> /home/ed/.cargo/registry/src/github.com-1ecc6299db9ec823/dioxus-cli-0.1.0/src/develop.rs:53:16
   |
53 |         .watch(src_dir.join("src"), RecursiveMode::Recursive)
   |                ^^^^^^^^^^^^^^^^^^^
   |                |
   |                expected `&std::path::Path`, found struct `std::path::PathBuf`
   |                help: consider borrowing here: `&src_dir.join("src")`

error[E0308]: mismatched types
  --> /home/ed/.cargo/registry/src/github.com-1ecc6299db9ec823/dioxus-cli-0.1.0/src/develop.rs:57:16
   |
57 |         .watch(src_dir.join("examples"), RecursiveMode::Recursive)
   |                ^^^^^^^^^^^^^^^^^^^^^^^^
   |                |
   |                expected `&std::path::Path`, found struct `std::path::PathBuf`
   |                help: consider borrowing here: `&src_dir.join("examples")`

Some errors have detailed explanations: E0308, E0599.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `dioxus-cli` due to 3 previous errors
warning: build failed, waiting for other jobs to finish...
error: failed to compile `dioxus-cli v0.1.0`, intermediate artifacts can be found at `/tmp/cargo-installUlWQ20`

Caused by:
  build failed

I'm currently running Windows 10, but performed the above in WSL 2, in an Ubuntu VM. Some details about my system:

Edition	Windows 10 Pro
Version	21H2
Installed on	‎2021-‎11-‎18
OS build	19044.1415
Experience	Windows Feature Experience Pack 120.2212.3920.0

todomvc.rs checkbox didn't work

Hi there, have you noticed the examples/todomvc.rs seemed not to function, each item could not be checked, thus there is no way to make a item to be completed.

set a field to optional.

I have to make a component, but I want set some field to optional, that mean is if the render don't have give the field value, then I can give it a default value.

rAF + controlled inputs and fast input leads to cursor jump

Reminiscent of:

Andarist/react-textarea-autosize#100

If we update an input value twice in one frame, we get cursor jumping. This is because of rAF batching the two updates that happened in one frame. In reality, if we get a "synchronous" event, then it should be handled synchronously.

... the joys of following the footsteps of others.

To fix in web, we need to progress the VirtualDom from within the handler. Specifically for inputs/textareas.

To fix in desktop, we need to explicitly segment the two updates across frames, or nullify the first update.

For now, the problem is fixed enough in both platforms that it only appears during key spam.

Subtree Attributes

As part of subtrees, we should implement "Subtree Attributes" to drive platform-specific things like the document title, head, meta tags, etc.

This can let us implement cross-platform abstractions around things like location so we can have our router code work the same even across the net (for liveview).

Access to native event type in web

It should be possible to access the native event that caused the event listener to fire in Dioxus web.

Unfortunately there's no way to access the event natively in Dioxus Desktop (webview) - though we could hold the event in stasis and provide some wrappers through FFI.

Make VirtualDom `Send` or provide `Send` variant

The VirtualDom is not Send which makes it challenging to hold across await points in web frameworks for liveview or SSR.

Either we need to develop our own web framework (with the same level of ergonomics of Diouxs) or somehow get the VirtualDom threadsafe to Send across threads.

Web: custom string interning

In the web, we use wasm-bindgens intern feature to cache strings on the js/rust boundary. However, this approach forces us to come up with a list of strings at compile-time. Instead, we should implement our own interning feature that uses a bloom filter and a configurable amount of cached elements, or some sort of better heuristic (like length). The time to cache/uncache is pretty significant in benchmarks, and it's unnatural to tell users to pre-populate the string cache if they want good performance.

Restart use_future based on other state changing

I've been working with Futures and Dioxus and am having a lot of trouble getting my futures to re-load. I'm trying to a flow similar to a browser where there is a URL bar at the top, and the content is reloaded when the URL changes.

The problem I'm having is that if I have content being loaded from a Future, I have to manually notice that the parameters I'm passing into the future have been invalidated and call restart on it. Here's a stripped version of what I'm working on:

fn app(cx: Scope) -> Element {
    let state = use_state(&cx, || ClientState::Disconnected);
    let url = use_state(&cx, || String::from("ws://localhost:8080/ws"));
    let client_url = use_state(&cx, || Option::<Url>::None);
    let client = if let ClientState::Connected(url) = state.get() {
        let url = url.clone();
        Some(use_future(&cx, || async move {
            let url = dbg!(Url::parse(&url).map_err(|err| err.to_string())?);

            Client::build(url)
                .finish()
                .await
                .map_err(|err| err.to_string())
        }))
    } else {
        None
    };
    cx.render(rsx! {
        div {
            class: "container m-3",
            match state.get() {
                ClientState::Disconnected => {
                   cx.render(rsx!{"Connect to a BonsaiDb server."})
                }
                ClientState::Connected(_) => {
                    cx.render(
                        match client.and_then(|c| c.value()) {
                            Some(Ok(client)) => {
                                rsx!(list_databases(client: client))
                            }
                            Some(Err(err)) => {
                                alert(err, "alert-danger")
                            },
                            None => rsx!{ div{ "loading..." } }        
                        }
                    )
                }
            }
        }
    })
}

#[derive(Props)]
struct ListDatabaseProps<'a> {
    client: &'a Client,
}

fn list_databases<'a>(cx: Scope<'a, ListDatabaseProps<'a>>) -> Element<'a> {
    let client = cx.props.client.clone();
    let databases = use_future(&cx, || async move { dbg!(client.list_databases().await) });
    cx.render(match databases.value() {
        Some(Ok(databases)) =>{...}
        Some(Err(err)) => alert(err, "alert-danger"),
        None => rsx! { div { "loading databases" }},
    })
}

When the URL changes, I get a new client (confirmed via debug logging), but the future in list_databases doesn't restart. To make this work I'll have to detect that the client has changed manually and restart the future.

Is there a way to be able to tie the use_future to depend on another UseState, so that it automatically restarts when that state is invalidated?

Need for synchronous PreventDefault across Tao/Wry boundary

Unfortunately, there's no way today to conditionally call PreventDefault across the Tao/Wry boundary.

Developers should be able to disable default in a way that's not just hardcoded fields - IE allowing default behavior when right-clicking links in the browser.

The FFI boundary is particularly challenging because we cannot synchronously handle the event.

I think the solution is to always trap the event and prevent default.

Then, ff 1) the event has default behavior and 2) the user didn't prevent that default behavior in their Dioxus handler, then we should craft the event again and push it back in the real dom.

event `onsubmit` field `value` problem

onsubmit FormData value is just can get the form element attr: value, but is not for the all form-data, like:

<form id="x_form" value="XXX_VALUE">
    <input name="test-1" />
    <input name="test-2" />
</form>

for the submit, we need get all form in this element, like test-1 and test-2 value, but its just can get the value of "XXX_VALUE"

tracking issue for subtree memoization

A major performance feature of Dioxus is complete elimination of static subtrees. So, subtrees within rsx! calls that have no dynamic calls can be "constified" and would be extremely cheap to generate.

This means that entirely-static structures like

                thead {
                    tr { class: "text-xs text-gray-500 text-left",
                        th { class: "pb-3 font-medium", "Transaction ID" }
                        th { class: "pb-3 font-medium", "Date" }
                        th { class: "pb-3 font-medium", "E-mail" }
                        th { class: "pb-3 font-medium", "Subscription" }
                        th { class: "pb-3 font-medium", "Status" }
                    }
                }

Would be completely skipped during the diffing process.

We can implement this today but there is some safety considerations to be aware of when hashing these structures. Primarily, if we compare two hashes and the second hash was manually created to be the same as another tree, then we would fail to update call functions for components, leading to missing state/unconnected lifetimes.

You would need to craft these structures intentionally, so it's extremely unlikely for any issue to pop up, but we don't want to directly expose a guaranteed way of causing UB into user code.

tracker for initial release

Docs

  • Documentation website generated
  • Documentation website guides ready
  • Documentation website tutorials ready for each platform
  • Documentation reference
  • Crates are sufficiently documented
  • Examples are ready and clean

Technical

  • Listeners actually drop their contents
  • Event delegator for webview and mobile
  • Controlled components work as advertised
  • HTML macro works as advertised
  • "Garbage collection" phase (dropping outdated elements, clearing listeners, remove/replace)
  • Keys work as advertised in elements/components
  • The powerful keyed diffing approach is finally included again
  • Safety of core mechanisms is closely evaluated again
  • use_task and immediate task system are re-evaluated
  • Heuristics engine
  • pause-able cooperative scheduler
  • rehydration implemented properly
  • basic const/static generated this will be part of the "templates" update

Ecosystem

  • A router
  • A cross-platform codeblock system
  • Studio/CLI is given better error messages and a proper live-reloading system (with local sockets and stuff)
  • extension is officially released (blocked by studio)
  • assets crate gets some basic functionality/sketches punting until later

Release

  • Official releases cut for all major crates
  • Social Media posts

Blockers

  • event bubbling
  • effects exposed to mutations effects are now just tasks but handled through the use_effect hook in hooks
  • noderefs exposed to mutations might punt node refs into the next update
  • hard allocations for props
  • miri says we leak memory
  • more guards/safety/debug assertions
  • more tests
  • resolve nodelinks as children
  • Suspense
  • Tasks
  • docs
  • site
  • router

SCSS support?

How hard would it be to make an application with SCSS? Is that already posible or maybe planned?

Is it possible to reference a local asset? such as an image

The following does not render the image correctly.

rsk! {
  cx,
  img { src: "src/assets/images/logo.png" }
}

It results in a broken link like this ...

image

The broken image has the following url link https://wry.index.html/src/assets/images/logo.png

None of these worked either

  • src/assets/images/logo.png
  • /src/assets/images/logo.png
  • /assets/images/logo.png
  • assets/images/logo.png

Is it possible to use a local image resource?

If so, how? I have not been able to find any examples that have local images.

Thanks for the help

How to solve "error: linking with `cc` failed: exit status: 1" in Mac OS

I encountered the problem when I try to launch the demo in Mac OS, the details below:
error: linking with cc failed: exit status: 1
= note: Undefined symbols for architecture x86_64:
"_UCKeyTranslate", referenced from:
tao::platform_impl::platform::event::get_modifierless_char::h82c48132d8e4db04 in libtao-4d0591e38d01f123.rlib(tao-4d0591e38d01f123.tao.f570f3ca-cgu.2.rcgu.o)
"_CGDisplayCreateUUIDFromDisplayID", referenced from:
_$LT$tao..platform_impl..platform..monitor..MonitorHandle$u20$as$u20$core..cmp..PartialEq$GT$::eq::h2b490f1950e1775b in libtao-4d0591e38d01f123.rlib(tao-4d0591e38d01f123.tao.f570f3ca-cgu.0.rcgu.o)
tao::platform_impl::platform::monitor::MonitorHandle::ns_screen::h7a220b61d2167bf2 in libtao-4d0591e38d01f123.rlib(tao-4d0591e38d01f123.tao.f570f3ca-cgu.0.rcgu.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Please help me and explain the reason if possible

component event bind failed

In the docs, the event handler bind like:

#[derive(Props)]
struct ClickableProps<'a> {
    onclick: EventHandler<'a, MouseEvent>
}

fn clickable(cx: Scope<ClickableProps>) -> Element {
    cx.render(rsx!(
        a { 
            onclick: move |evt| cx.props.onclick.call(evt)
        }
    ))
}

But in the current version, the EventHandler don't need the second arg: MouseEvent, and the evt type is UiEvent<MouseData> but the onclick.call must be have the type of AnyEvent.

html-side templates

A huge opportunity for Dioxus is to leverage templates on the HTML side to beat out regular Dom patching.

Right now, we send streams of patches from the VDOM into the renderer. This means that we're constantly building the same structures over and over and over, even if they're exactly the same.

For structures like:

rsx!(
                tr { class: "text-xs {is_even}", key: "{asin}"
                    td { class: "py-5 px-6 font-medium", "{asin}" }
                    td { class: "font-medium", "{Product_Details}" }
                    td { class: "font-medium", "[email protected]" }
                    td { class: "font-medium", "Monthly" }
                    td {
                        span { class: "inline-block py-1 px-2 text-white bg-green-500 rounded-full",
                            "Completed"
                        }
                    }
                }
)

We could save the entire rsx! call as a template and then clone that template whenever this call is rendered. Instead of building the entire template from scratch, we would simply clone an existing iteration of this template and then modify it only in the places where content is different.

The precursor of this work would be #39 where we can actually identify these structures.

This feature is how the Vanilla JS framework benchmark is so fast - they just clone the same templates into place.

Add support for native platform ui such as gtk-rs, uikit, winapps, fltk

Coping content from: https://old.reddit.com/r/rust/comments/rv9hru/releasing_dioxus_v01_a_new_rust_gui_toolkit_for/hrc0gbz/?context=3

prabirshrestha:
This looks awesome. Are the plans to support platform native ui frameworks such as gtk-rs and UIKit? Having all controls would cause maintenance headache but I think having example on how to use Gtk-rs with dioxus with few controls would be a good start. This would allow me to easily create dioxus components backed by gtk-rs.
I think this has a potential to take over react-native if it can support platform native controls. Having core component abstraction such as View, Text, Image could be a good start. https://reactnative.dev/docs/components-and-apis#basic-components
Would love to see an official support for platform native ui components that doesn't depend on html and javascript.

jkelleyrtp:
That's the plan! To pop the hood open a little bit, we have a type called Mutations which essentially describes what needs to be patched in the real renderer to make it look like the VirtualDom's understanding of the world.
https://github.com/DioxusLabs/dioxus/blob/master/packages/core/src/mutations.rs
You can implement entirely new elements, attributes, and listeners that integrate with the rsx! macro. Right now, the HTML namespace is supported through a collection of zero-sized-types and some traits to make things fit together:
https://docs.rs/dioxus-html/0.1.3/dioxus\_html/
If you wanted to add a new fundamental language to rsx!, or even just components, it's entirely possible. I'd love to see native macOS / GTK / win apps using the same set of common primitives.

(creating this issue so I can subscribe to it and get notified on updates).

I'm personally interested in native platform ui without html and javascript.
For gtk-rs here are some good references:

ui kit resources:

Links should open in webbrowser by default

Right now, if you click on a link in Dioxus Desktop, the webview will try to link within the webview. However, that's not at all how Dioxus apps should work: all external links should open in the web browser.

Crash passing strings between components

Problem

While passing a string (from html input element) up to a parent node, the program sometimes crashes trying to mutate a cell that's currently being mutated.

Diagnosis Steps

It's unclear to me exactly why the crash is occuring, the following revealed nothing useful:

  • Running under debug mode (thread generating crash is all assembly)
  • Running with "RUST_BACKTRACE=full" (never links back to any code in main.rs, crashing thread is spawned from tokio)
    Full backtrace

I will concede that the code generating this crash is prototype-grade. However, all compiler and clippy lints pass (except non_snake_case due to dioxus style).

My speculation is that this has to do with my "onsend" propery not using the correct bounds, or requiring some wrapper, but I don't have a solution yet.

Here's the full project .zip

Platform information

Rust Target: x86_64-unknown-linux-gnu
Rust Version: 1.57.0 (rustup installed)
Linux Version: 5.14.21-2-MANJARO

I haven't tried on any other platforms.

final blockers

  • event bubbling
  • effects exposed to mutations effects are now just tasks but handled through the use_effect hook in hooks
  • noderefs exposed to mutations
  • hard allocations for props
  • miri says we leak memory
  • more guards/safety/debug assertions
  • more tests
  • resolve nodelinks as children
  • Suspense
  • Tasks
  • docs
  • site
  • router

request: abstract over `Document` in all renderers so things like routers work properly

HTML's Document has some important goodies that we should allow exposed in a cross-platform way between web and desktop.

https://www.w3schools.com/jsref/dom_obj_document.asp

Right now, to use Document in the web, you have to go through websys/gloo. However, to use it in Desktop, you would have to assemble some javascript on the desktop side. We should provide a unified hook or something similar that abstracts over Document functionality for all platforms - so we can set things like title in a cross-platform way.

exe took long to display result on win10

After installing webview2 runtime, the demo worked. But in the demo file-explorer, it took several seconds to display the result. And the exe generated a folder called file-explorer.exe.WebView2, and there were many files inside.

Hello world example fails on windows

Just tried to do the hello world example for windows and got a not implemented panic:

thread 'main' panicked at 'not implemented: path index.html/',[PATH]\dioxus-desktop-0.1.3\src\lib.rs:347:26
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
webview2: panic in callback function. Aborting because it's UB to unwind across FFI boundaries.
error: process didn't exit successfully: `target\debug\hello.exe` (exit code: 0xc0000409, STATUS_STACK_BUFFER_OVERRUN)

main.rs

use dioxus::prelude::*;


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

fn App(cx: Scope) -> Element {
    cx.render(rsx! (
        div { "Hello, world!" }
    ))
}
[dependencies]
dioxus = { version = "0.1.5", features = ["desktop"] }

Tried the example a few times, each time cleaning and starting fresh with the same result. Can add more info if you need, bit new to adding issues to repos.

Formatting with rustfmt

Currently, rustfmt fails on code using the rsx! macro. Would it be possible for this to work?

Alternatively, is there any way to create markup without using the macro?

avoid Infinite-loop

I find if I call a function in app init, and if this function will change some state in app, then the app will infinite-loop, I think this problem we need prevent.

fn app(cx: Scope) -> Element {

let text = use_read(&cx, TEXT);

todo_function(&cx);

cx.render(rsx!(
    h1 { "{text}" }
))
}

I think this problem need developer attention, so I write this issue qwq

internals: unify webview and web interpreter

Currently the web and webview share different interpreter code - it would be nice to move to either a completely wasm-based interpreter or a pure JavaScript/TypeScript interpreter. The appropriate steps have been taken - JS code refactored out and event system is now configured to always use serialized events.

`element` disabled attribute

Cannot use disabled attribute like:

// cx.props.disabled = true
button {
  disabled: "{cx.props.disabled}",
  "Button",
}

the button state always be disabled.

but you can use this code to do it:

let is_disabled = if disabled { "disabled" } else { "" };
rsx!{
   "{is_disabled}": "true"
}

Some questions about handling events

hello,i'm writing an app using dioxus, but I have some difficulties:

  1. How to handle close windows event
button { class: "bg-red-500 m-1 w-3 h-3 rounded-full",
    onclick: move |evt| {
        // TODO:  app exit
         println!("close windows:{:?}",evt);
    }
}
  1. How to handle system events when the app is hidden.

I can only handle events of a certain tag now, but sometimes have to deal with system some shortcut keys

  1. Change CSS properties on event(click), looks like:
$('#image').click(function() {
  $('#foo').addClass('myClass');
});

event `onsubmit` field `value` problem

onsubmit FormData value is just can get the form element attr: value, but is not for the all form-data, like:

<form id="x_form" value="XXX_VALUE">
    <input name="test-1" />
    <input name="test-2" />
</form>

for the submit, we need get all form in this element, like test-1 and test-2 value, but its just can get the value of "XXX_VALUE"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.