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

React Native useEffect异步调用触发警告 如何正确实现座位状态查询功能

问题原因

核心警告触发原因是直接将async函数作为useEffect的回调参数:async函数执行后默认返回Promise对象,而useEffect仅允许回调返回清理函数,因此触发规则警告。
除此之外现有代码还存在隐藏问题:

  • 封装的状态逻辑函数未遵循React自定义Hookuse开头的命名规范,可能触发Hook规则校验错误
  • useEffect依赖项为空,当seat、vid参数变化时不会重新请求最新的座位状态
  • 没有请求中断逻辑,组件卸载后请求完成仍执行setColor会触发内存泄漏警告
直接修复方案

调整useEffect中异步函数的写法,将async函数定义在useEffect内部执行,补充依赖项和清理逻辑即可:

// 自定义Hook遵循use开头的命名约定
const useSeatColor = (seat, vid) => {
  // 给定默认颜色,避免初始渲染无样式
  const [color, setColor] = useState('green');

  useEffect(() => {
    // 声明中断控制器,用于组件卸载时终止未完成的请求
    const abortController = new AbortController();
    // 异步函数定义在useEffect内部,不直接作为useEffect的回调
    const fetchSeatStatus = async () => {
      try {
        const response = await fetch(
          `http://192.168.8.100/dbops/actions/seat_status.php?seat=${seat}&vid=${vid}`,
          { signal: abortController.signal }
        );
        const result = await response.json();
        setColor(result.message);
      } catch (err) {
        // 主动中断的请求跳过错误处理
        if (err.name !== 'AbortError') {
          console.error('获取座位状态失败', err);
        }
      }
    };

    fetchSeatStatus();
    // 返回清理函数,组件卸载时终止请求
    return () => abortController.abort();
  }, [seat, vid]); // 把参数加入依赖项,参数变化时自动重新请求

  return color;
};

// 调用方式不变,仅把函数名改为use开头的Hook名
const vid = 4;
const seat1Color = useSeatColor(1, vid);
const seat2Color = useSeatColor(2, vid);
const seat3Color = useSeatColor(3, vid);
const seat4Color = useSeatColor(4, vid);

修改后即可消除警告,原有功能不受影响。

更优实现方案

原有方案每个座位单独发起一次请求,20个座位会发起20次请求,性能损耗较高,建议调整为一次性请求所有座位状态,减少网络开销,同时可以避免重复的渲染代码:

const SeatPage = () => {
  const vid = 4;
  // 用对象存储所有座位的颜色,key为座位号,value为对应颜色
  const [seatColors, setSeatColors] = useState({});

  useEffect(() => {
    const abortController = new AbortController();
    const fetchAllSeatStatus = async () => {
      try {
        // 调整后端接口,一次性返回当前vid下所有座位的状态,返回格式示例:{1:"red",2:"green",3:"red"...}
        const response = await fetch(
          `http://192.168.8.100/dbops/actions/all_seat_status.php?vid=${vid}`,
          { signal: abortController.signal }
        );
        const result = await response.json();
        setSeatColors(result);
      } catch (err) {
        if (err.name !== 'AbortError') {
          console.error('获取所有座位状态失败', err);
        }
      }
    };
    fetchAllSeatStatus();
    return () => abortController.abort();
  }, [vid]);

  return (
    <Screen style={{ paddingBottom: 5 }}>
      {/* 用循环渲染座位,避免重复代码,20个座位只需调整数组范围即可 */}
      {[1,2,3,4].map(seatNum => (
        <TouchableOpacity key={seatNum} style={styles.seat}>
          <MaterialCommunityIcons 
            name="seat" 
            size={40} 
            color={seatColors[seatNum] || 'green'} 
          />
          <Button 
            title={String(seatNum)} 
            style={{ width: 20 }} 
            color={seatColors[seatNum] || 'green'} 
          />
        </TouchableOpacity>
      ))}
      <View style={styles.seat}></View>
      <View style={styles.seat}></View>
    </Screen>
  )
}

内容的提问来源于stack exchange,提问作者Julius Peter Odeke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 17:54:03