Starting with Yew: Are all these clones needed for a callback? #3535
-
Hi, I just started with Yew, and I'm going through the tutorial, but I'm also trying to write a simple The first thing that I wanted to do for this app is to get a list of all the todos. I want to select from this list, such that I can show the detail page for the selected item. I ran into a couple of
But that gave me the err output:
I fixed it quite easily, but I have a nagging feeling that the fix is not quite how I should do it. Can anyone provide feedback? I hope it's ok if I ask the most basic questions. I provided a more detailed working example below. // task_list.rs
use uuid::Uuid;
use yew::prelude::*;
use crate::models::task::Task;
#[derive(PartialEq, Properties)]
pub struct TaskListProps {
tasks: Vec<Task>,
selected_task: Option<Uuid>,
onselect: Callback<Uuid, ()>
}
#[function_component]
pub fn TaskList(props: &TaskListProps) -> Html {
let TaskListProps { tasks, selected_task, onselect } = props;
// I have no clue how to make this work:
//
// let onselect = onselect.reform(move |id| {
// props.selected_task.replace(id);
// id
// });
html! {
<ul>
{
tasks.iter().map(|task| {
html! {
<TaskListItem
task={task.clone()}
selected={selected_task.as_ref() == Some(task.id())}
onselect={onselect}
/>
}
}).collect::<Html>()
}
</ul>
}
}
#[derive(PartialEq, Properties)]
pub struct TaskListItemProps {
task: Task,
selected: bool,
onselect: Callback<Uuid, ()>,
}
#[function_component]
pub fn TaskListItem(props: &TaskListItemProps) -> Html {
let TaskListItemProps { task, onselect, .. } = props;
// Are these clones/copies needed, or have I struck an anti-pattern?
let onselect = onselect.clone();
let id = *task.id();
// Otherwise err-output:
// "borrowed data escapes outside of function
// `props` escapes the function body here
// `props` is a reference that is only valid in the function body"
let onclick = Callback::from(move |_: MouseEvent| {
onselect.emit(id)
});
html! {
<li key={task.id().to_u128_le()} onclick={onclick}>
<span>{task.title()}</span>
</li>
}
} // task.rs
use uuid::Uuid;
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Task {
id: Uuid,
title: String,
}
impl Task {
// Constructor method for creating a new task
pub fn new(title: String) -> Self {
Task {
id: Uuid::new_v4(),
title,
}
}
// Getter methods for Task
pub fn id(&self) -> &Uuid {
&self.id
}
pub fn title(&self) -> &String {
&self.title
}
// -- snip -- setters
}
// -- snip -- other impls |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Nevermind I think I got it. I shouldn't have read the getting started page, but the tutorial, my bad. Resulting code: use crate::models::task::Task;
use uuid::Uuid;
use yew::prelude::*;
#[derive(PartialEq, Properties)]
pub struct TaskListProps {
pub tasks: Vec<Task>,
pub onselect: Callback<Uuid, ()>,
#[prop_or_default]
pub selected_task: Option<Uuid>,
}
#[function_component]
pub fn TaskList(props: &TaskListProps) -> Html {
let TaskListProps {
tasks,
selected_task,
onselect,
} = props;
let selected_task = use_state(|| selected_task.clone());
let onselect = {
let selected_task = selected_task.clone();
onselect.reform(move |id: Uuid| {
selected_task.set(Some(id));
id
})
};
let items = tasks
.iter()
.map(|task| {
html! {
<TaskListItem
task={task.clone()}
selected={selected_task.as_ref() == Some(task.id())}
onselect={onselect.clone()}
/>
}
})
.collect::<Html>();
html! { <ul class="list-group"> { items } </ul> }
}
#[derive(PartialEq, Properties)]
struct TaskListItemProps {
task: Task,
selected: bool,
onselect: Callback<Uuid, ()>,
}
#[function_component]
fn TaskListItem(props: &TaskListItemProps) -> Html {
let TaskListItemProps { task, selected, onselect } = props;
let onclick = {
let id = *task.id();
onselect.reform( move |_| id)
};
html! {
<li
key={task.id().to_u128_le()}
onclick={onclick}
class={
let active = if *selected {
"active"
} else {
"list-group-item "
};
format!("list-group-item {}", active)
}
>
<span>{task.title()}</span>
</li>
}
} |
Beta Was this translation helpful? Give feedback.
Nevermind I think I got it. I shouldn't have read the getting started page, but the tutorial, my bad.
Resulting code: