React setState数组条目丢失:聊天界面消息覆盖问题求助
React Native聊天消息丢失问题修复
你的问题核心是setState的闭包陷阱:
当用户发送消息后,setTimeout里的异步操作会捕获调用handleSendPress时的messages旧值。等1秒后添加机器人消息时,它会基于这个旧数组拼接,而不是当前最新的包含用户消息的数组,导致之前的消息被覆盖。
修复方案
把addMessage里的setMessages改成函数式更新,这种方式会接收当前最新的state作为参数,彻底避免闭包带来的旧值问题:
const addMessage = (message: MessageType.Any) => { setMessages(prevMessages => [message, ...prevMessages]); };
原理说明
React的setState如果传入函数,会确保这个函数拿到的是当前最新的state快照。不管异步操作延迟多久执行,都能基于最新的消息数组添加新消息,不会出现覆盖旧消息的情况。
完整修复代码
import React, { useState } from 'react'; import { Chat, MessageType } from '@flyerhq/react-native-chat-ui' import { SafeAreaProvider } from 'react-native-safe-area-context' const uuidv4 = () => { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = Math.floor(Math.random() * 16) const v = c === 'x' ? r : (r % 4) + 8 return v.toString(16) }) }; const user = { id: uuidv4(), firstName: 'User1' }; const chatbot = { id: uuidv4(), firstName: 'User2' }; const App = () => { const [messages, setMessages] = useState<MessageType.Any[]>([]) const addMessage = (message: MessageType.Any) => { // 改用函数式更新获取最新state setMessages(prevMessages => [message, ...prevMessages]); }; const handleSendPress = (message: MessageType.PartialText) => { const textMessage: MessageType.Text = { author : user, createdAt: Date.now(), id : uuidv4(), text : message.text, type : 'text', }; addMessage(textMessage); setTimeout(() => { const chatbotTextMessage: MessageType.Text = { author : chatbot, createdAt: Date.now(), id : uuidv4(), text : `Response that won't erase user's messages...`, type : 'text', }; addMessage(chatbotTextMessage); }, 1000); }; return ( <SafeAreaProvider> <Chat messages={messages} showUserNames={true} onSendPress={handleSendPress} user={user} /> </SafeAreaProvider> ); } export default App;
内容的提问来源于stack exchange,提问作者Tommy B.
相关产品推荐
相关产品推荐

