Skip to content

Commit

Permalink
more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 committed Sep 21, 2024
1 parent a05a216 commit a3ef5c6
Show file tree
Hide file tree
Showing 11 changed files with 366 additions and 33 deletions.
2 changes: 1 addition & 1 deletion book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
- [State Management](./learn/state_management.md)
- [Signals](./learn/state_management/signals.md)
- [Global Signals](./learn/state_management/global_signals.md)
- [Dioxus Hooks](./learn/dioxus_hooks.md)
- [Lifecycle](./learn/lifecycle.md)
- [Context](./learn/state_management/context.md)
- [Third Party](./learn/state_management/third_party.md)
- [Async](./learn/async.md)
Expand Down
3 changes: 3 additions & 0 deletions book/src/learn/animation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ fn app() -> Element {
ctx.with(AnimNum::new(0., 100.).time(200))
});

// Retrive the animation you returned in `use_animation`
let width = animation.get().read().as_f32();

rsx!(rect {
Expand All @@ -21,6 +22,7 @@ fn app() -> Element {
background: "blue"
})
}
```

Advanced Example:

Expand All @@ -46,6 +48,7 @@ fn app() -> Element {
)
});

// Retrieve the animations you returned inside `use_animation`
let (width, color) = animation.get();

rsx!(rect {
Expand Down
31 changes: 21 additions & 10 deletions book/src/learn/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
Freya apps will usually be composed of different components.
Components are defined in the form functions that might receive some input as **Props** and return the UI as **Element**.

> You can learn more about how the UI is defined in the [UI](./ui.md) chapter.
This is how a simple root component looks like:

```rs
// Usually, the root component of a Freya app is named `app`,
// but it is not a requirement
fn app() -> Element {
rsx!(
label {
Expand All @@ -16,29 +20,29 @@ fn app() -> Element {
```

This is obviously fine, but the moment our app grows in size and complexity we might want to split
things out in order to maintain a certain level of modularity and reusability. We can do this with components.

For example:
things out in order to maintain a certain level of modularity and reusability. We can do this by spliting the UI in different components

This is how a simple root component looks like:
For example, lets create a reusable component:

```rs
// Root component that gets passed to the `launch` function
fn app() -> Element {
rsx!(
// By declaring this element using `TextLabel`
// we are creating an instance of that component
TextLabel {
"Number 1"
}
label {
"Number 2"
}
// Another instance of the same component
TextLabel {
"Number 3"
}
)
}

// Reusable component
// Reusable component that we might call as many times we want
#[component]
fn TextLabel(text: String) -> Element {
rsx!(
Expand All @@ -49,7 +53,7 @@ fn TextLabel(text: String) -> Element {
}
```

Notice how we anotate our `TextLabel` component with the macro `#[component]`, this will transform every argument of the function (just `text: String` in this case) to a component prop, so we can later use the component in a declarative way in the RSX.
Notice how we anotate our `TextLabel` component with the macro `#[component]`, this will transform every argument of the function (just `text: String` in this case) to a component prop, so we can later use the component prop in a declarative way in the RSX.

For more complex components you might want to put the props in an external struct intead of using the `#[components]` macro:

Expand All @@ -70,19 +74,26 @@ fn TextLabel(TextLabelProps { text }: TextLabelProps) -> Element {

## Renders

Components renders are just when a component function runs, which might be because it is subscribed to a signal and that signal got mutated. Consider this simple component:
Components renders are just when a component function runs, which might be because it is subscribed to a signal and that signal got mutated, or because its props changed.

> Even though the naming might give you the impression that it means the app will effectively rerender again, it has nothing to do with it, in fact, a component might render a thousand times but it it doesn't generate a new UI Freya will not rerender it.
Consider this simple component:

```rs
#[component]
fn CoolComp() -> Element {
let mut count = use_signal(|| 0);

// 1 run of this function = 1 render of this component
// So, everytime the `count` signal is mutated, the component rerenders.
// 1 run of this function means 1 render of this component
// So, everytime the `count` signal is mutated, the component rerenders/is recalled.

rsx!(
label {
// Update the signal value
onclick: move |_| count += 1,

// By embedding the count in this text the component is subscried to any change in the `count` siganal
"Increase {count}"
}
)
Expand Down
7 changes: 5 additions & 2 deletions book/src/learn/hooks.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
# Hooks

Hooks are special functions to be used inside of Components. They are usually prefixed with `use`, e.g `use_signal`, `use_effect`
Hooks are special functions to be used inside of Components that lets you handle different things like the state or lifecycle of your component. They are usually prefixed with `use`, e.g `use_signal`, `use_effect`, `use_memo`, etc.

# Rules of Hooks

Even though hooks appear to be normal functions they are in fact special so you cannot just call them however you want.

## 1. They cannot be called conditionally

You cannot do the following because hooks need to maintain their order.
You cannot do the following because hooks need to maintain their order. So, if one component is calling 3 different hooks in one render, and then in another render if just calls 2, it would be breaking this rule.

❌:
```rs
#[component]
fn MyComponent(value: bool) -> Element {
let is_enabled = if value {
// This should be moved out of the conditional
use_signal(|| value)
} else {
true
Expand Down
74 changes: 73 additions & 1 deletion book/src/learn/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,76 @@

You may add i18n (localization) support to your Freya app by using the [**dioxus-i18n**](https://github.com/dioxus-community/dioxus-i18n) crate.

[Code Example](https://github.com/dioxus-community/dioxus-i18n/blob/main/examples/freya.rs).
```fluent
# en-US.ftl
hello_world = Hello, World!
hello = Hello, {$name}!
```


```fluent
# es-ES.ftl
hello_world = Hola, Mundo!
hello = Hola, {$name}!
```

```rs
// main.rs

fn main() {
launch(app);
}

#[allow(non_snake_case)]
fn Body() -> Element {
// Access to the i18n state
let mut i18n = i18n();

// Update the current language
let change_to_english = move |_| i18n.set_language(langid!("en-US"));
let change_to_spanish = move |_| i18n.set_language(langid!("es-ES"));

rsx!(
rect {
rect {
direction: "horizontal",
Button {
onclick: change_to_english,
label {
"English"
}
}
Button {
onclick: change_to_spanish,
label {
"Spanish"
}
}
}

// Get and subscribe to these messages
label { { t!("hello_world") } }
label { { t!("hello", name: "Dioxus") } }
}
)
}

fn app() -> Element {
// Initialize our i18n config
use_init_i18n(|| {
I18nConfig::new(langid!("en-US"))
.with_locale(Locale::new_static(
langid!("en-US"),
include_str!("./en-US.ftl"),
))
.with_locale(Locale::new_dynamic(
langid!("es-ES"),
"./examples/es-ES.ftl",
))
});

rsx!(Body {})
}
```
73 changes: 73 additions & 0 deletions book/src/learn/lifecycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Lifecycle

Dioxus components can use hooks to manage certain lifecycle situations.

## Component creation
You can run certain logic when the component is created for the first time by using the `use_hook` hook.

```rs
fn app() -> Element {

use_hook(|| {
println!("Component running for the first time!");
});

rsx!(...)
}
```

## Component destroyment

Run some logic when the component is being destroyed.

```rs
fn app() -> Element {

use_drop(|| {
println!("Component is being dropped.");
});

rsx!(...)
}
```

## Side effects

Run some logic when a signal is changed.

```rs
fn app() -> Element {
let mut signal = use_signal(|| 1);

use_effect(move || {
// Because we are reading this signal now the effect is subscribed to any change
let value = signal();
println!("Value of signal is {value}");
});

rsx!(...)
}
```

## Side effects with dependencies

Run some logic when a signal is changed.

```rs
fn app() -> Element {
let mut signal = use_signal(|| 1);
let mut other_signal = use_signal(|| 1);

// Manually specify non-signal values that we might want to react to
use_effect(use_reactive(&signal, |value| {
println!("Value of signal is {value}");
}));

// When you need multiple values you can pass a tuple
use_effect(use_reactive(&(signal, other_signal), |(value, other_signal)| {
println!("Value of signals are {value} and {other_signal}");
}));

rsx!(...)
}
```
2 changes: 1 addition & 1 deletion book/src/learn/state_management.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# State Management

Dioxus and thus Freya apps, don't have a single type of state management.
Dioxus and Freya apps, have multiple ways of state management.

See the different options:

Expand Down
Loading

0 comments on commit a3ef5c6

Please sign in to comment.