Internationalization: move guide to en folder and preserve its history. (#494)

* chore: move guide to en folder

* docs: add english as language
This commit is contained in:
Jon Kelley authored and GitHub committed 2022-07-09 12:31:46 -04:00
1 parent 7fdc72726d
commit c97ca7dff6
69 files changed
+4 -1

No files matched your search

+110
View File
@@ -0,0 +1,110 @@
# Local State
The first step to dealing with complexity in your app is to refactor your state to be purely local. This encourages good code reuse and prevents leakage of abstractions across component boundaries.
## What it looks like
Let's say we're managing the state for a list of Todos. Whenever we edit the todo, we want the list to update. We might've started building our app but putting everything into a single `use_ref`.
```rust
struct Todo {
contents: String,
is_hovered: bool,
is_editing: bool,
}
let todos = use_ref(&cx, || vec![Todo::new()]);
cx.render(rsx!{
ul {
todos.read().iter().enumerate().map(|(id, todo)| rsx!{
li {
onhover: move |_| *todos.write()[id].is_hovered = true,
h1 { "{todo.contents}" }
}
})
}
})
```
As shown above, whenever the todo is hovered, we want to set its state:
```rust
todos.write()[0].is_hovered = true;
```
As the amount of interactions goes up, so does the complexity of our state. Should the "hover" state really be baked into our data model?
Instead, let's refactor our Todo component to handle its own state:
```rust
#[inline_props]
fn Todo<'a>(cx: Scope, todo: &'a Todo) -> Element {
let is_hovered = use_state(&cx, || false);
cx.render(rsx!{
li {
h1 { "{todo.contents}" }
onhover: move |_| is_hovered.set(true),
}
})
}
```
Now, we can simplify our Todo data model to get rid of local UI state:
```rust
struct Todo {
contents: String,
}
```
This is not only better for encapsulation and abstraction, but it's only more performant! Whenever a Todo is hovered, we won't need to re-render *every* Todo again – only the Todo that's currently being hovered.
Wherever possible, you should try to refactor the "view" layer *out* of your data model.
## Immutability
Storing all of your state inside a `use_ref` might be tempting. However, you'll quickly run into an issue where the `Ref` provided by `read()` "does not live long enough." An indeed – you can't return locally-borrowed value into the Dioxus tree.
In these scenarios consider breaking your `use_ref` into individual `use_state`s.
You might've started modeling your component with a struct and use_ref
```rust
struct State {
count: i32,
color: &'static str,
names: HashMap<String, String>
}
// in the component
let state = use_ref(&cx, State::new)
```
The "better" approach for this particular component would be to break the state apart into different values:
```rust
let count = use_state(&cx, || 0);
let color = use_state(&cx, || "red");
let names = use_state(&cx, HashMap::new);
```
You might recognize that our "names" value is a HashMap – which is not terribly cheap to clone every time we update its value. To solve this issue, we *highly* suggest using a library like [`im`](https://crates.io/crates/im) which will take advantage of structural sharing to make clones and mutations much cheaper.
When combined with the `make_mut` method on `use_state`, you can get really succinct updates to collections:
```rust
let todos = use_state(&cx, im_rc::HashMap::default);
todos.make_mut().insert("new todo", Todo {
contents: "go get groceries",
});
```
## Moving on
This particular local patterns are powerful but is not a cure-all for state management problems. Sometimes your state problems are much larger than just staying local to a component.