Yew:嵌套回调的困难
Yew: Difficulty with nested callbacks
我正在尝试做一些我认为非常基本的事情:我有一个下拉菜单,我希望该下拉菜单的 onchange 事件使程序根据用户的请求从后端获取一些数据输入。 (然后,你知道的,根据他们选择的第一件事为用户提供更多选项。真的很简单,而且我似乎应该能够找到一种简单的方法来做到这一点。)
此最小(失败)示例的完整代码位于:https://github.com/djmcmath/broken-yew
但是相关位的行为不正确,如下所示:
- 视图函数令人愉快地呈现一个迭代列表。我传递了一个回调,所以它知道在“onchange”事件上要做什么。
- 回调被执行了,这让我很高兴。但它没有调用 Msg::GetData。这个可以编译,很好,但是不能用,不太好。
我很惭愧地承认,我花了几个星期的空闲时间来解决这个问题。我认为这与范围和生命周期有关。我认为我进行此编译的方式 - 通过克隆上下文并使用“移动”将其与我需要进行此工作的实际上下文断开连接。但是我在示例和参考文献中找到的主题的每一个变体都抱怨范围或生命周期。
在此先感谢您的帮助。
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::GetData(value) => {
log::info!("Start 'fetch' with user-selected value: {}", value);
ctx.link().send_future(async {
match fetch_markdown("url_shortened_for_clarity").await {
Ok(md) => Msg::SetMarkdownFetchState(FetchState::Success(md)),
Err(err) => Msg::SetMarkdownFetchState(FetchState::Failed(err)),
}
});
false
},
Msg::SetMarkdownFetchState(fetch_state) => {
let mut wr = WebReturn { term_id: 0, dow: 0, dep_time_num: 0 };
match fetch_state {
FetchState::Success(s) => { wr = serde_json::from_str(&s).expect(&format!("Poorly formatted JSON! {}", s).to_string()); },
FetchState::Failed(f) => { log::info!("Fetch failed: {}", f); },
FetchState::NotFetching => {},
FetchState::Fetching => {}
};
log::info!("term_id (3) : {}, dep_time_num (12000) : {}, and dow (3) : {}", wr.term_id, wr.dep_time_num, wr.dow);
true
}
}
}
fn view(&self, ctx:&Context<Self>) -> Html {
let ctx_link = ctx.link().clone();
let my_callback: Callback<String> = Callback::from(move |value: String| {
let val_as_num = value.parse::<i32>().unwrap_or(0);
log::info!("Returned value: {}", val_as_num);
ctx_link.callback(|val_as_num: i32| Msg::GetData(val_as_num));
});
html! {
<div>
{ self.render_list(&self.props.term_list, my_callback) }
</div>
}
}
此行不会“回调”您的组件,它创建一个回调然后不调用它:
ctx_link.callback(|val_as_num: i32| Msg::GetData(val_as_num));
您需要改为在回调中调用 .send_message()
,或者更好的是,使用 .callback()
:
创建原始回调
let my_callback = ctx_link.callback(|value: String| {
let val_as_num = value.parse::<i32>().unwrap_or(0);
log::info!("Returned value: {}", val_as_num);
Msg::GetData(val_as_num)
});
我正在尝试做一些我认为非常基本的事情:我有一个下拉菜单,我希望该下拉菜单的 onchange 事件使程序根据用户的请求从后端获取一些数据输入。 (然后,你知道的,根据他们选择的第一件事为用户提供更多选项。真的很简单,而且我似乎应该能够找到一种简单的方法来做到这一点。)
此最小(失败)示例的完整代码位于:https://github.com/djmcmath/broken-yew
但是相关位的行为不正确,如下所示:
- 视图函数令人愉快地呈现一个迭代列表。我传递了一个回调,所以它知道在“onchange”事件上要做什么。
- 回调被执行了,这让我很高兴。但它没有调用 Msg::GetData。这个可以编译,很好,但是不能用,不太好。
我很惭愧地承认,我花了几个星期的空闲时间来解决这个问题。我认为这与范围和生命周期有关。我认为我进行此编译的方式 - 通过克隆上下文并使用“移动”将其与我需要进行此工作的实际上下文断开连接。但是我在示例和参考文献中找到的主题的每一个变体都抱怨范围或生命周期。
在此先感谢您的帮助。
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::GetData(value) => {
log::info!("Start 'fetch' with user-selected value: {}", value);
ctx.link().send_future(async {
match fetch_markdown("url_shortened_for_clarity").await {
Ok(md) => Msg::SetMarkdownFetchState(FetchState::Success(md)),
Err(err) => Msg::SetMarkdownFetchState(FetchState::Failed(err)),
}
});
false
},
Msg::SetMarkdownFetchState(fetch_state) => {
let mut wr = WebReturn { term_id: 0, dow: 0, dep_time_num: 0 };
match fetch_state {
FetchState::Success(s) => { wr = serde_json::from_str(&s).expect(&format!("Poorly formatted JSON! {}", s).to_string()); },
FetchState::Failed(f) => { log::info!("Fetch failed: {}", f); },
FetchState::NotFetching => {},
FetchState::Fetching => {}
};
log::info!("term_id (3) : {}, dep_time_num (12000) : {}, and dow (3) : {}", wr.term_id, wr.dep_time_num, wr.dow);
true
}
}
}
fn view(&self, ctx:&Context<Self>) -> Html {
let ctx_link = ctx.link().clone();
let my_callback: Callback<String> = Callback::from(move |value: String| {
let val_as_num = value.parse::<i32>().unwrap_or(0);
log::info!("Returned value: {}", val_as_num);
ctx_link.callback(|val_as_num: i32| Msg::GetData(val_as_num));
});
html! {
<div>
{ self.render_list(&self.props.term_list, my_callback) }
</div>
}
}
此行不会“回调”您的组件,它创建一个回调然后不调用它:
ctx_link.callback(|val_as_num: i32| Msg::GetData(val_as_num));
您需要改为在回调中调用 .send_message()
,或者更好的是,使用 .callback()
:
let my_callback = ctx_link.callback(|value: String| {
let val_as_num = value.parse::<i32>().unwrap_or(0);
log::info!("Returned value: {}", val_as_num);
Msg::GetData(val_as_num)
});