# dx-utils
Utility components and functions for [Dioxus](https://dioxuslabs.com/) fullstack apps.
## Components
### `LocalTime`
Renders an RFC 3339 datetime string as a `<time>` element in the browser's
local timezone.
- **During SSR**: displays UTC (e.g. `2025-06-15 14:30`).
- **On the client** (post-hydration): `use_effect` + `js_sys::Date` converts
to the browser's local timezone. No JavaScript eval or global scripts.
**Props:**
| `datetime` | `String` | — | RFC 3339 datetime string (required) |
| `class` | `String` | `""` | Optional CSS class on `<time>` |
```rust
use dioxus::prelude::*;
use dx_utils::LocalTime;
#[component]
fn UsageRow(hour_bucket: String) -> Element {
rsx! {
td { LocalTime { datetime: hour_bucket } }
}
}
```
## Functions
### `redirect_external(url: &str)`
Redirect to an external URL. Works correctly during both SSR and client-side
navigation.
- **During SSR**: sets HTTP 302 status and a `Location` header via
`FullstackContext`, producing a real HTTP redirect before any HTML reaches the
browser.
- **On the client** (post-hydration): uses `navigator().replace()` with
`NavigationTarget::External` for a client-side navigation.
```rust
use dioxus::prelude::*;
use dx_utils::redirect_external;
#[component]
fn AuthGuard() -> Element {
let auth = use_server_future(|| check_auth())?;
let binding = auth.read();
let status = binding.as_ref().and_then(|r| r.as_ref().ok());
if let Some(s) = status {
if !s.authenticated {
redirect_external(&s.login_url);
return rsx! {};
}
}
rsx! { Outlet::<Route> {} }
}
```
## Usage
Add to your `Cargo.toml`:
```toml
[dependencies]
dx-utils = "0.2"
[features]
server = ["dx-utils/server"]
```
## Features
| `server` | Enables SSR redirect via `FullstackContext` and `http` crate |
## Requirements
- Dioxus 0.7+
- Rust 1.75+
## License
MIT