A starter template for Dioxus Desktop apps, with Tailwind & Nix support.
Act as starter project for writing new desktop apps using Dioxus, along with
- Nix support
- Author's preferred tools
- Tailwind
This repository is still a work-in-progress. Here's the current progress:
- Nix
- Devshell
- Nix package
- Simple
nix build/nix run - Nix package containing macOS app bundle
- Nix package for Linux
- Simple
- Deployment
- macOS bundling
- Linux bundling
- Tailwind
- Routes & navigation
- Application state (via
dioxus-signalsfrom 0.5)
Stretch goals:
- macOS Application menu entries
In the nix develop shell, run:
just watch
just bundle
nix run github:srid/dioxus-desktop-template
# Or just `nix run` in the project directory
This repository began in large part to understand how to manage application state in Dioxus Desktop apps, and come up with some best demonstrable practices for it.
- Shared read-only state
- In the top
Appcomponent, useuse_shared_state_providerto initialize the application state. - In inner components, use
use_shared_state::<T>, followed by a.read()on it, to access the current state value. - The state can be changed to a new value, but not mutated. There is no per-field granularity.
- In the top
- Shared state, that can be modified (from anywhere in the component tree)
- We use dioxus-signals (requires Dioxus from Git) to provide fine-grained mutation and component rerendering.
- In the top
Appcomponent, useuse_context_provider(cx, AppState::new()); - In inner components, use
let state: AppState = *use_context(cx).unwrap();to access the current state value. - Make individual fields of the state struct a
Signaltype- The state struct should use
Signalfor its field types. Nested tree ofSignals is the idiom.
- The state struct should use
- Use
state.<field>to render a component based on a field signal- Use
dioxus_signals::use_selectorto produce a derived signal
- Use
- Component re-renders when only relevant subset of the state changes
- State modification that relies on a long-running blocking task
- Write async modifier methods on the state struct, and have them update the field signals.
- In the UI components, use
use_futureto invoke these async methods to update the state before the component is renderer (or upon an user event).
This project uses rust-flake to keep flake.nix minimal.
- Blank screen on Linux? See NixOS/nixpkgs#32580
WEBKIT_DISABLE_COMPOSITING_MODE=1 nix run