异步回调更新数据源,无法触发列表渲染

问题代码

// xxx.ets 
@Observed 
export class ObservedArray<T> extends Array<T> { 
  constructor(args?: T[]) { 
    if (args instanceof Array) { 
      super(...args); 
    } else { 
      super(); 
    } 
  } 
} 
 
@Observed 
export class ChatItemModel { 
  id_: string; 
  content: string; 
 
  constructor(msgId: string, content: string) { 
    this.id_ = msgId; 
    this.content = content; 
  } 
} 
 
@Observed 
export class ChatListModel { 
  public chatItems: ObservedArray<ChatItemModel> = new ObservedArray<ChatItemModel>(); 
 
  fetChatList() { 
    setTimeout(() => { 
      for (let i = 0; i < 30; i++) { 
        this.chatItems.push(new ChatItemModel(i.toString(), `小李${i}今天晚上放学不要走`)); 
      } 
    }, 2000); 
  } 
} 
 
@Entry 
@Component 
export struct ChatList { 
  @State chatListModel: ChatListModel = new ChatListModel(); 
 
  aboutToAppear() { 
    this.chatListModel.fetChatList(); 
  } 
 
  build() { 
    List() { 
      ForEach( 
        this.chatListModel.chatItems, 
        (chatItem: ChatItemModel) => { 
          ListItem() { 
            Text(chatItem.content) 
              .margin({ left: 20, right: 20 }) 
          } 
          .height(60) 
          .width('100%') 
        }, 
        (chatItem: ChatItemModel): string => { 
          return chatItem.id_; 
        }) 
    } 
    .height('100%') 
    .width('100%') 
  } 
}
HarmonyOS
2024-02-20 15:28:00
浏览
收藏 0
回答 2
待解决
回答 2
按赞同
/
按时间
OwenOO

ArkUI无法监听对象中数组属性的push变化,可以通过设置该数组对象触发UI界面刷新。

示例代码

// xxx.ets 
@Observed 
export class ChatListModel { 
  public chatItems: ObservedArray<ChatItemModel> = new ObservedArray<ChatItemModel>(); 
 
  fetChatList() { 
    setTimeout(() => { 
      let arr: ObservedArray<ChatItemModel> = new ObservedArray<ChatItemModel>(); 
      for (let i = 0; i < 30; i++) { 
        arr.push(new ChatItemModel(i.toString(), `小李${i}今天晚上放学不要走`)); 
      } 
      this.chatItems = arr; 
    }, 2000); 
  } 
}
分享
微博
QQ
微信
回复
2024-02-20 20:21:43
忙忙忙困困困

问题可能出在列表渲染时数据源更新的时机。由于​​setTimeout​​​是异步操作,它会在2秒后执行​​fetChatList​​​方法,而在这段时间内,列表已经被渲染完成,此时数据源​​chatItems​​中还没有数据,因此无法触发列表的重新渲染。

为了解决这个问题,您可以在数据源更新后手动触发列表的重新渲染。一种简单的方法是在​​setTimeout​​的回调函数中添加一行代码来通知应用程序数据已经更新,需要重新渲染列表。这可以通过使用状态管理工具或类似的机制来实现。

另外,您也可以考虑使用React Hooks中的​​useState​​和​​useEffect​​来管理数据和副作用,这样可以更方便地处理数据更新和重新渲染列表的逻辑。


下面是一个简单的示例代码,演示如何使用React Hooks中的​​useState​​​和​​useEffect​​来处理数据更新和重新渲染列表的逻辑:

import { useState, useEffect } from 'react';

// ChatItemModel定义和ObservedArray定义与您提供的代码相同

export const ChatList = () => {
  const [chatItems, setChatItems] = useState<ChatItemModel[]>([]);

  const fetchChatList = () => {
    setTimeout(() => {
      const newChatItems: ChatItemModel[] = [];
      for (let i = 0; i < 30; i++) {
        newChatItems.push(new ChatItemModel(i.toString(), `小李${i}今天晚上放学不要走`));
      }
      setChatItems(newChatItems);
    }, 2000);
  };

  useEffect(() => {
    fetchChatList();
  }, []); // 第二个参数传入空数组,表示只在组件挂载时执行一次

  return (
    <div>
      {chatItems.map((chatItem) => (
        <div key={chatItem.id_}>
          <p>{chatItem.content}</p>
        </div>
      ))}
    </div>

在这个示例中,我们使用​​useState​​来定义​​chatItems​​状态,用于存储聊天列表数据。在​​fetchChatList​​函数中,通过​​setTimeout​​模拟异步获取数据,并在数据获取后使用​​setChatItems​​更新​​chatItems​​状态。然后使用​​useEffect​​来在组件挂载时调用​​fetchChatList​​函数获取数据。

最后,在返回的JSX中,我们使用​​map​​方法遍历​​chatItems​​数组,渲染每个聊天项的内容。

分享
微博
QQ
微信
回复
2024-02-27 08:33:37
相关问题
焦点事件onBlur/onFocus无法触发
1998浏览 • 1回复 待解决
lazyforeach替换数据源解决方案
701浏览 • 1回复 待解决
OpenHarmony idl如何实现异步
4672浏览 • 1回复 待解决
嵌套Class的属性变化无法触发UI渲染
269浏览 • 1回复 待解决
如何更新页面列表数据
6930浏览 • 1回复 待解决