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

react-native-gifted-chat消息状态更新失败及API异常处理求助

问题分析与解决方案

你遇到的核心问题是React状态的不可变性原则以及状态更新时机的问题:直接修改messageToSend的属性不会触发组件重渲染,而且你在API请求完成前就调用了setMessages,后续的状态修改无法同步到UI中。另外,react-native-gifted-chat完全支持处理发送失败的状态,我们可以通过自定义消息状态和渲染逻辑来实现。

具体修复步骤

1. 遵循不可变状态更新原则

React状态更新依赖于创建新的对象/数组,而不是直接修改原有的状态值。直接修改messageToSend的属性不会让React感知到状态变化,自然不会更新UI。

2. 分阶段更新消息状态

  • 第一步:先创建带有pending: true的消息副本,添加到消息列表中,让用户立刻看到发送中的状态。
  • 第二步:API请求成功/失败后,找到对应的消息,替换其状态属性(pending、sent、failed),并更新状态触发重渲染。

3. 处理发送失败状态

我们可以给消息添加failed字段,然后通过renderMessage自定义组件来渲染失败状态的样式(比如红色背景、"发送失败"提示)。

修改后的完整代码

function SmsConversations({ route }) { 
  const onSend = useCallback((messages = []) => { 
    const [messageToSend] = messages;
    // 创建带pending状态的消息副本,确保有唯一ID(用时间戳兜底)
    const pendingMessage = {
      ...messageToSend,
      pending: true,
      sent: false,
      failed: false,
      _id: messageToSend._id || Date.now()
    };

    // 先添加"发送中"的消息到状态
    setMessages(prevMessages => GiftedChat.append(prevMessages, pendingMessage));

    // 调用发送API
    sendSMS(toNumber, fromNumber, pendingMessage.text) 
      .then((res) => {
        // API成功:更新消息状态为已发送
        setMessages(prevMessages => 
          prevMessages.map(msg => 
            msg._id === pendingMessage._id 
              ? { ...msg, pending: false, sent: true } 
              : msg
          )
        );
      }) 
      .catch((err) => {
        // API失败:标记消息为发送失败
        setMessages(prevMessages => 
          prevMessages.map(msg => 
            msg._id === pendingMessage._id 
              ? { ...msg, pending: false, sent: false, failed: true } 
              : msg
          )
        );
        console.error('短信发送失败:', err);
      });
  }, [toNumber, fromNumber]); // 别忘添加依赖,避免闭包导致的旧值问题

  // 自定义消息渲染:处理失败状态的显示
  const renderMessage = (props) => {
    const { currentMessage } = props;
    if (currentMessage.failed) {
      return (
        <View style={{ flexDirection: 'row', justifyContent: 'flex-end', marginVertical: 8, marginHorizontal: 12 }}>
          <View style={{ 
            backgroundColor: '#ffecec', 
            paddingHorizontal: 14, 
            paddingVertical: 8, 
            borderRadius: 18,
            borderColor: '#ff6b6b',
            borderWidth: 1
          }}>
            <Text style={{ color: '#333' }}>{currentMessage.text}</Text>
            <Text style={{ fontSize: 10, color: '#ff6b6b', marginTop: 4, textAlign: 'right' }}>发送失败</Text>
          </View>
        </View>
      );
    }
    // 非失败状态用默认渲染
    return <GiftedChat.Message {...props} />;
  };

  return ( 
    <GiftedChat 
      messages={messages} 
      onSend={(messages) => onSend(messages)} 
      user={{ _id: 1 }}
      renderMessage={renderMessage} // 启用自定义消息渲染
    /> 
  ); 
}

关键细节说明

  • 不可变更新:每次更新状态时都使用扩展运算符(...)创建新对象,确保React能检测到状态变化。
  • 消息匹配:通过_id来匹配需要更新的消息,保证修改的是对应的那条发送中的消息。
  • 依赖数组:useCallback的依赖要包含toNumber和fromNumber,避免闭包导致API调用时使用旧的参数值。
  • 失败状态渲染:利用GiftedChat提供的renderMessage属性,完全自定义失败消息的样式,提升用户体验。

内容的提问来源于stack exchange,提问作者Dexter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 23:47:39