Yew Rust循环渲染组件重复显示首个元素的问题咨询
Yew渲染组件列表重复显示第一个元素的问题解决
我使用Yew 0.20.0和Rust 1.67.1开发Web前端应用,User、Post、Vote是后端JSON对象的包装类型。从后端请求多个PostCard数据后,通过html!宏渲染时遇到问题:明明self.post_cards中有5个元素,渲染结果却总是重复显示第一个元素。遍历self.post_cards打印日志显示,JSON解析正常,数据与后端返回一致。
相关代码片段
数据添加逻辑
#[derive(Clone)] pub struct Index { post_cards: Vec<PostCard>, can_request: bool, current_index: u32, } ... if let Value::Array(v) = &json["data"] { for value in v { self.post_cards.push(PostCard::from_json(value.clone())); } }
视图渲染代码
fn view(&self, ctx: &Context<Self>) -> Html { html! { <> <Navbar/> <div> { self.post_cards.iter().map(|pc| { html!{ <PostCard post={pc.post.clone()} user={pc.user.clone()} vote={pc.vote.clone()} /> } }).collect::<Html>() } </div> <Footer/> </> } }
PostCard结构体定义
#[derive(Clone, PartialEq)] pub struct PostCard { pub post: Post, pub user: User, pub vote: Vote, }
排查过程
- 尝试硬编码指定下标渲染:比如下标>0时渲染第一个元素、>1时渲染第二个,这种方式能正常显示对应元素,但不适用于大量数据场景。
- 添加日志排查:在
html!宏的遍历中打印PostCard数据,结果显示数据正确;但在PostCard组件的create()方法中打印日志,发现仅第一个组件实例被创建,后续渲染复用了第一个实例,导致显示重复。
日志代码片段:
self.post_cards.iter().map(|pc| { log!("index.rs html!", pc.post.clone().text); html!{ <PostCard post={pc.post.clone()} user={pc.user.clone()} vote={pc.vote.clone()} /> } }).collect::<Html>() impl Component for PostCard { ... fn create(ctx: &Context<Self>) -> Self { log!("=== PostCard created === "); log!("PostCard post text\n", ctx.props().post.text.clone()); PostCard { post: ctx.props().post.clone(), user: ctx.props().user.clone(), vote: ctx.props().vote.clone(), } } ... }
解决方法
为PostCard组件实现changed()方法,手动更新组件内部状态并返回true触发重渲染,问题得到解决。
添加的changed()方法代码:
fn changed(&mut self, ctx: &Context<Self>, _old_props: &Self::Properties) -> bool { self.post = ctx.props().post.clone(); self.user = ctx.props().user.clone(); self.vote = ctx.props().vote.clone(); true }
确认说明
这是Yew中渲染组件列表的正确方式之一。Yew在列表渲染时会复用已有组件实例,当组件的props发生变化时,必须通过changed()方法手动同步内部状态,并返回true告知Yew需要重新渲染该组件。如果不实现changed(),组件会复用之前的状态,导致显示重复的旧数据。
内容的提问来源于stack exchange,提问作者radu781
相关产品推荐
相关产品推荐

