Fix the issue of duplicate unique ID for atoms using newtype.
The MergeFunctionsPass in LLVM merges identical functions (https://rust.godbolt.org/z/3nnr9nMne), resulting in the same function addresses.
This commit is contained in:
14 files changed
+74
-52
No files matched your search
@@ -95,7 +95,7 @@ Calling `deref` or `deref_mut` is actually more complex than it seems. When a va
|
||||
Sometimes you want a signal to propagate across your app, either through far-away siblings or through deeply-nested components. In these cases, we use Dirac: Dioxus's first-class state management toolkit. Dirac atoms automatically implement the Signal API. This component will bind the input element to the `TITLE` atom.
|
||||
|
||||
```rust
|
||||
const TITLE: Atom<String> = || "".to_string();
|
||||
const TITLE: Atom<String> = Atom(|| "".to_string());
|
||||
const Provider: Component = |cx|{
|
||||
let title = use_signal(cx, &TITLE);
|
||||
render!(input { value: title })
|
||||
@@ -131,7 +131,7 @@ By default, Dioxus is limited when you use iter/map. With the `For` component, y
|
||||
Dioxus automatically understands how to use your signals when mixed with iterators through `Deref`/`DerefMut`. This lets you efficiently map collections while avoiding the re-rendering of lists. In essence, signals act as a hint to Dioxus on how to avoid un-necessary checks and renders, making your app faster.
|
||||
|
||||
```rust
|
||||
const DICT: AtomFamily<String, String> = |_| {};
|
||||
const DICT: AtomFamily<String, String> = AtomFamily(|_| {});
|
||||
const List: Component = |cx|{
|
||||
let dict = use_signal(cx, &DICT);
|
||||
cx.render(rsx!(
|
||||
|
||||
@@ -146,7 +146,7 @@ async fn editor_service(rx: UnboundedReceiver<EditorCommand>) {
|
||||
We can combine coroutines with [Fermi](https://docs.rs/fermi/latest/fermi/index.html) to emulate Redux Toolkit's Thunk system with much less headache. This lets us store all of our app's state *within* a task and then simply update the "view" values stored in Atoms. It cannot be understated how powerful this technique is: we get all the perks of native Rust tasks with the optimizations and ergonomics of global state. This means your *actual* state does not need to be tied up in a system like Fermi or Redux – the only Atoms that need to exist are those that are used to drive the display/UI.
|
||||
|
||||
```rust
|
||||
static USERNAME: Atom<String> = |_| "default".to_string();
|
||||
static USERNAME: Atom<String> = Atom(|_| "default".to_string());
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
let atoms = use_atom_root(cx);
|
||||
@@ -159,7 +159,7 @@ fn app(cx: Scope) -> Element {
|
||||
}
|
||||
|
||||
fn Banner(cx: Scope) -> Element {
|
||||
let username = use_read(cx, USERNAME);
|
||||
let username = use_read(cx, &USERNAME);
|
||||
|
||||
cx.render(rsx!{
|
||||
h1 { "Welcome back, {username}" }
|
||||
@@ -177,8 +177,8 @@ enum SyncAction {
|
||||
}
|
||||
|
||||
async fn sync_service(mut rx: UnboundedReceiver<SyncAction>, atoms: AtomRoot) {
|
||||
let username = atoms.write(USERNAME);
|
||||
let errors = atoms.write(ERRORS);
|
||||
let username = atoms.write(&USERNAME);
|
||||
let errors = atoms.write(&ERRORS);
|
||||
|
||||
while let Ok(msg) = rx.next().await {
|
||||
match msg {
|
||||
|
||||
@@ -118,14 +118,14 @@ enum InputError {
|
||||
TooShort,
|
||||
}
|
||||
|
||||
static INPUT_ERROR: Atom<InputError> = |_| InputError::None;
|
||||
static INPUT_ERROR: Atom<InputError> = Atom(|_| InputError::None);
|
||||
```
|
||||
|
||||
Then, in our top level component, we want to explicitly handle the possible error state for this part of the tree.
|
||||
|
||||
```rust
|
||||
fn TopLevel(cx: Scope) -> Element {
|
||||
let error = use_read(cx, INPUT_ERROR);
|
||||
let error = use_read(cx, &INPUT_ERROR);
|
||||
|
||||
match error {
|
||||
TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
|
||||
@@ -139,7 +139,7 @@ Now, whenever a downstream component has an error in its actions, it can simply
|
||||
|
||||
```rust
|
||||
fn Commandline(cx: Scope) -> Element {
|
||||
let set_error = use_set(cx, INPUT_ERROR);
|
||||
let set_error = use_set(cx, &INPUT_ERROR);
|
||||
|
||||
cx.render(rsx!{
|
||||
input {
|
||||
|
||||
@@ -105,7 +105,7 @@ async fn editor_service(rx: UnboundedReceiver<EditorCommand>) {
|
||||
Podemos combinar corrotinas com `Fermi` para emular o sistema `Thunk` do **Redux Toolkit** com muito menos dor de cabeça. Isso nos permite armazenar todo o estado do nosso aplicativo _dentro_ de uma tarefa e, em seguida, simplesmente atualizar os valores de "visualização" armazenados em `Atoms`. Não pode ser subestimado o quão poderosa é essa técnica: temos todas as vantagens das tarefas nativas do Rust com as otimizações e ergonomia do estado global. Isso significa que seu estado _real_ não precisa estar vinculado a um sistema como `Fermi` ou `Redux` – os únicos `Atoms` que precisam existir são aqueles que são usados para controlar a interface.
|
||||
|
||||
```rust
|
||||
static USERNAME: Atom<String> = |_| "default".to_string();
|
||||
static USERNAME: Atom<String> = Atom(|_| "default".to_string());
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
let atoms = use_atom_root(cx);
|
||||
@@ -118,7 +118,7 @@ fn app(cx: Scope) -> Element {
|
||||
}
|
||||
|
||||
fn Banner(cx: Scope) -> Element {
|
||||
let username = use_read(cx, USERNAME);
|
||||
let username = use_read(cx, &USERNAME);
|
||||
|
||||
cx.render(rsx!{
|
||||
h1 { "Welcome back, {username}" }
|
||||
@@ -134,8 +134,8 @@ enum SyncAction {
|
||||
}
|
||||
|
||||
async fn sync_service(mut rx: UnboundedReceiver<SyncAction>, atoms: AtomRoot) {
|
||||
let username = atoms.write(USERNAME);
|
||||
let errors = atoms.write(ERRORS);
|
||||
let username = atoms.write(&USERNAME);
|
||||
let errors = atoms.write(&ERRORS);
|
||||
|
||||
while let Ok(msg) = rx.next().await {
|
||||
match msg {
|
||||
|
||||
@@ -113,14 +113,14 @@ enum InputError {
|
||||
TooShort,
|
||||
}
|
||||
|
||||
static INPUT_ERROR: Atom<InputError> = |_| InputError::None;
|
||||
static INPUT_ERROR: Atom<InputError> = Atom(|_| InputError::None);
|
||||
```
|
||||
|
||||
Então, em nosso componente de nível superior, queremos tratar explicitamente o possível estado de erro para esta parte da árvore.
|
||||
|
||||
```rust
|
||||
fn TopLevel(cx: Scope) -> Element {
|
||||
let error = use_read(cx, INPUT_ERROR);
|
||||
let error = use_read(cx, &INPUT_ERROR);
|
||||
|
||||
match error {
|
||||
TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
|
||||
@@ -134,7 +134,7 @@ Agora, sempre que um componente _downstream_ tiver um erro em suas ações, ele
|
||||
|
||||
```rust
|
||||
fn Commandline(cx: Scope) -> Element {
|
||||
let set_error = use_set(cx, INPUT_ERROR);
|
||||
let set_error = use_set(cx, &INPUT_ERROR);
|
||||
|
||||
cx.render(rsx!{
|
||||
input {
|
||||
|
||||
Reference in new issue
Block a user