React Native异步修改props数据后子组件未读图标偶发不渲染问题求助
问题根源
- 直接修改props不会触发重渲染:你在异步获取未读消息后直接修改传入的
clientsprop属性,React的渲染更新依赖状态引用变化,直接修改原对象属性不会触发重渲染,只有刚好在首次渲染前拿到数据时图标才会显示,否则就会缺失,和你判断的「修改时机在渲染完成后」本质一致。 getUnreadMessagesProccess的执行时机错误:当前对应的useEffect依赖为空数组,仅在组件首次挂载时执行一次,后续clientsprop更新时不会重新拉取未读消息,也会导致数据不匹配。- ClientItem状态冗余导致不同步:额外维护的
showIcon状态仅在client.unreadMessages大于0时赋值为true,没有处理归零场景,且初始渲染时useEffect未执行,若初始就有未读消息也会出现图标不显示的问题。
修复方案
第一步:调整ClientList的状态逻辑,不直接修改props
首先在ClientList中新增本地状态存储处理后带未读数量的客户列表,修改未读消息处理逻辑,生成新的数组对象触发重渲染,同时补全useEffect依赖:
// 新增本地状态 const [processedClients, setProcessedClients] = useState<Client[]>([]) // 补全useEffect依赖,clients更新时重新拉取未读 useEffect(() => { if (clients?.length) { getUnreadMessagesProccess().then(r => console.log("aaaaaaaaa")); } }, [clients, userId, pubnub]); // 修改getUnreadMessagesProccess里的处理逻辑,不要修改原clients async function getUnreadMessagesProccess() { const tokens = ['1000']; const channels = ['1234567']; const auth = await setGrant(); const channelMetadata = await getMetadata(); setChannelsAndTokens(channelMetadata, channels, tokens); const unread = await getUnreadedMessages(channels, tokens).then((res) => { // 生成新数组、新对象,触发重渲染 const newClients = clients.map(client => ({ ...client, unreadMessages: res.channels[`${client.id}-${userId}-chat`] || 0 })) setProcessedClients(newClients) console.log(res); }); return unread; } // FlatList的data替换为processedClients <FlatList keyExtractor={item => item.id.toString()} data={processedClients} // 其余属性保持不变 />
第二步:简化ClientItem逻辑,删除冗余状态
直接根据props传入的unreadMessages判断图标显示,不需要额外维护本地状态,避免同步问题:
// 删除showIcon相关的useEffect和state定义,渲染部分直接写: <View style={styles.dot_container}> {client.unreadMessages > 0 && <FontAwesome5 name="comment-dots" size={20} color={Colors.red} />} </View>
可选优化
如果clients是全局存储在Redux中的数据,可以把未读消息的更新逻辑放到Redux切片中统一处理,所有用到客户列表的组件都可以直接拿到最新的未读数量,避免重复拉取。
内容的提问来源于stack exchange,提问作者user2994290
相关产品推荐
相关产品推荐

