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

React中useEffect无限循环问题:状态未变更却重复触发执行

问题分析与解决方案

无限循环的根源

  1. 组件顶层直接触发状态更新:你在组件函数的顶层直接调用了retrieveItemStatus(),这会导致每次组件渲染时都会执行这个异步函数。函数内部的updateStatuses(tempStatuses)会修改itemStatuses状态,触发组件重新渲染,如此反复形成无限循环。
  2. 对象引用导致无效状态更新:retrieveItemStatus中生成的tempStatuses每次都是新的对象(无论是从AsyncStorage解析的,还是从默认JSON生成的),即使内容和当前itemStatuses完全一致,由于对象引用不同,updateStatuses依然会触发组件重新渲染。

修复步骤

  1. 将初始化逻辑限制为单次执行
    把retrieveItemStatus()的调用移到依赖为空的useEffect里,确保组件挂载时只执行一次,避免每次渲染都触发状态更新:
useEffect(() => {
  retrieveItemStatus();
}, []);

同时删除原来组件顶层的retrieveItemStatus();调用。

  1. 避免不必要的状态更新
    在调用updateStatuses前,对比新状态和当前状态的内容,只有当内容不同时才更新状态,减少无效渲染:
const retrieveItemStatus = async () => {
  var tempStatuses;
  try {
    const value = await AsyncStorage.getItem("@item_Statuses");
    if (value !== null) {
      tempStatuses = JSON.parse(value); // JSON.parse是同步函数,无需await
    } else {
      tempStatuses = JSON.parse(
        JSON.stringify(require("../default-statuses.json"))
      ); // 同样去掉不必要的await
    }
    // 对比内容,仅当不同时更新状态
    if (JSON.stringify(tempStatuses) !== JSON.stringify(itemStatuses)) {
      updateStatuses(tempStatuses);
    }
  } catch (error) {}
};
  1. 用useState管理items变量
    你当前用var items普通变量存储数据,组件重新渲染时会被重置,无法正确触发视图更新。改用useState来管理:
const [items, setItems] = useState([]);

// 在copyData函数中替换items = itemsCopy为:
setItems(itemsCopy);

修复后的完整代码示例

const App = () => {
  const [items, setItems] = useState([]);
  const [itemStatuses, updateStatuses] = useState({});

  const retrieveItemStatus = async () => {
    var tempStatuses;
    try {
      const value = await AsyncStorage.getItem("@item_Statuses");
      if (value !== null) {
        tempStatuses = JSON.parse(value);
      } else {
        tempStatuses = JSON.parse(
          JSON.stringify(require("../default-statuses.json"))
        );
      }
      if (JSON.stringify(tempStatuses) !== JSON.stringify(itemStatuses)) {
        updateStatuses(tempStatuses);
      }
    } catch (error) {}
  };

  useEffect(() => {
    retrieveItemStatus();
  }, []);

  useEffect(() => {
    const copyData = async () => {
      const itemsCopy = [];

      const coll = collection(db, "Items");
      const querySnapshots = await getDocs(coll);
      const docsArr = querySnapshots.docs;
      docsArr.forEach((doc) => { // 用forEach替代map,无需返回新数组
        var data = doc.data();
        if (itemStatuses[data.name] === "locked") return;
        itemsCopy.push(data);
      });
      setItems(itemsCopy);
    };

    copyData();

  }, [itemStatuses]);

  return (
    <View style={styles.container}>
      <Text>temp.......</Text>
    </View>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 00:57:36