0.4 Migration Guide
This guide will outline the API changes between the 0.4
and 0.5
releases.
0.5
has includes significant changes to hooks, props, and global state.
Cheat Sheet
Here is a quick cheat sheet for the changes:
Scope
Dioxus 0.4:
fn app(cx: Scope) -> Element { cx.use_hook(|| { /*...*/ }); cx.provide_context({ /*...*/ }); cx.spawn(async move { /*...*/ }); cx.render(rsx! { /*...*/ }) }
Dioxus 0.5:
use dioxus::prelude::*; // In dioxus 0.5, the scope is no longer passed as an argument to the function fn app() -> Element { // Hooks, context, and spawn are now called directly use_hook(|| { /*...*/ }); provide_context({ /*...*/ }); spawn(async move { /*...*/ }); rsx! { /*...*/ } }
Props
Dioxus 0.4:
#[component] fn Comp(cx: Scope, name: String) -> Element { // You pass in an owned prop, but inside the component, it is borrowed (name is the type &String inside the function) let owned_name: String = name.clone(); cx.render(rsx! { "Hello {owned_name}" BorrowedComp { "{name}" } }) } #[component] fn BorrowedComp<'a>(cx: Scope<'a>, name: &'a str) -> Element<'a> { cx.render(rsx! { "Hello {name}" }) } #[derive(Props, PartialEq)] struct ManualProps { name: String } fn ManualPropsComponent(cx: Scope<ManualProps>) -> Element { cx.render(rsx! { "Hello {cx.props.name}" }) }
Dioxus 0.5:
use dioxus::prelude::*; // In dioxus 0.5, props are always owned. You pass in owned props and you get owned props in the body of the component #[component] fn Comp(name: String) -> Element { // Name is owned here already (name is the type String inside the function) let owned_name: String = name; rsx! { "Hello {owned_name}" BorrowedComp { name: "{owned_name}" } ManualPropsComponent { name: "{owned_name}" } } } // Borrowed props are removed in dioxus 0.5. Mapped signals can act similarly to borrowed props if your props are borrowed from state // ReadOnlySignal is a copy wrapper over a state that will be automatically converted to #[component] fn BorrowedComp(name: ReadOnlySignal<String>) -> Element { rsx! { "Hello {name}" } } // In dioxus 0.5, props need to implement Props, Clone, and PartialEq #[derive(Props, Clone, PartialEq)] struct ManualProps { name: String, } // Functions accept the props directly instead of the scope fn ManualPropsComponent(props: ManualProps) -> Element { rsx! { "Hello {props.name}" } }
You can read more about the new props API in the Props Migration guide.
Futures
Dioxus 0.4:
use_future((dependency1, dependency2,), move |(dependency1, dependency2,)| async move { /*use dependency1 and dependency2*/ });
Dioxus 0.5:
// dependency1 and dependency2 must be Signal-like types like Signal, ReadOnlySignal, GlobalSignal, or another Resource use_resource(|| async move { /*use dependency1 and dependency2*/ });
Read more about the use_resource
hook in the Hook Migration guide.
State Hooks
Dioxus 0.4:
let copy_state = use_state(cx, || 0); let clone_local_state = use_ref(cx, || String::from("Hello")); use_shared_state_provider(cx, || String::from("Hello")); let clone_shared_state = use_shared_state::<String>(cx); let copy_state_value = **copy_state; let clone_local_state_value = clone_local_state.read(); let clone_shared_state_value = clone_shared_state.read(); cx.render(rsx!{ "{copy_state_value}" "{clone_shared_state_value}" "{clone_local_state_value}" button { onclick: move |_| { copy_state.set(1); *clone_local_state.write() = "World".to_string(); *clone_shared_state.write() = "World".to_string(); }, "Set State" } })
Dioxus 0.5:
// You can now use signals for local copy state, local clone state, and shared state with the same API let mut copy_state = use_signal(|| 0); let mut clone_shared_state = use_context_provider(|| Signal::new(String::from("Hello"))); let mut clone_local_state = use_signal(|| String::from("Hello")); // Call the signal like a function to clone the current value let copy_state_value = copy_state(); // Or use the read method to borrow the current value let clone_local_state_value = clone_local_state.read(); let clone_shared_state_value = clone_shared_state.read(); rsx! { "{copy_state_value}" "{clone_shared_state_value}" "{clone_local_state_value}" button { onclick: move |_| { // All three states have the same API for updating the state copy_state.set(1); clone_shared_state.set("World".to_string()); clone_local_state.set("World".to_string()); }, "Set State" } }
Read more about the use_signal
hook in the State Migration guide.
Fermi
Dioxus 0.4:
use dioxus::prelude::*; use fermi::*; static NAME: Atom<String> = Atom(|_| "world".to_string()); fn app(cx: Scope) -> Element { use_init_atom_root(cx); let name = use_read(cx, &NAME); cx.render(rsx! { div { "hello {name}!" } Child {} ChildWithRef {} }) } fn Child(cx: Scope) -> Element { let set_name = use_set(cx, &NAME); cx.render(rsx! { button { onclick: move |_| set_name("dioxus".to_string()), "reset name" } }) } static NAMES: AtomRef<Vec<String>> = AtomRef(|_| vec!["world".to_string()]); fn ChildWithRef(cx: Scope) -> Element { let names = use_atom_ref(cx, &NAMES); cx.render(rsx! { div { ul { names.read().iter().map(|f| rsx!{ li { "hello: {f}" } }) } button { onclick: move |_| { let names = names.clone(); cx.spawn(async move { names.write().push("asd".to_string()); }) }, "Add name" } } }) }
Dioxus 0.5:
use dioxus::prelude::*; // Atoms and AtomRefs have been replaced with GlobalSignals static NAME: GlobalSignal<String> = Signal::global(|| "world".to_string()); fn app() -> Element { rsx! { // You can use global state directly without the use_read or use_set hooks div { "hello {NAME}!" } Child {} ChildWithRef {} } } fn Child() -> Element { rsx! { button { onclick: move |_| *NAME.write() = "dioxus".to_string(), "reset name" } } } // Atoms and AtomRefs have been replaced with GlobalSignals static NAMES: GlobalSignal<Vec<String>> = Signal::global(|| vec!["world".to_string()]); fn ChildWithRef() -> Element { rsx! { div { ul { for name in NAMES.read().iter() { li { "hello: {name}" } } } button { onclick: move |_| { // No need to clone the signal into futures, you can use it directly async move { NAMES.write().push("asd".to_string()); } }, "Add name" } } } }
You can read more about global signals in the Fermi migration guide.