You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 21:54:55