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

React Native中useEffect的正确使用方式:解决组件卸载后更新未挂载组件状态的警告

Understanding the Problem

The warning "Can't perform a React state update on an unmounted component" pops up because your async function getPerMonthCharges might finish executing after the OwnerView component has been unmounted from the DOM. When that happens, calling setMonthlyCharge tries to update state on a component that no longer exists—React flags this as an unnecessary, risky operation.

In your current code, the useEffect runs once when the component mounts, but there's no mechanism to stop or ignore the async function's state update if the component unmounts before the operation completes.

Fixing the Issue

We can add a mounted flag inside the useEffect to track whether the component is still mounted. If the component unmounts before the async operation finishes, we'll skip updating the state entirely. Here's the corrected code:

const OwnerView = () => {
  const [monthlyCharge, setMonthlyCharge] = useState(0);

  useEffect(() => {
    // Flag to track if the component is still mounted
    let isMounted = true;

    async function getPerMonthCharges(ownerPhoneNumber, noOfCars) {
      console.log(`inside getPerMonthCharges`);
      try {
        const serviceProviderChargesDoc = await firestore()
          .collection(`${serviceProviderId}_charges`)
          .doc(`${ownerPhoneNumber}`)
          .get();
        
        // Only update state if the component is still mounted
        if (isMounted && serviceProviderChargesDoc?.data()?.chargesPerMonth > 0) {
          setMonthlyCharge(serviceProviderChargesDoc?.data()?.chargesPerMonth);
          return;
        }
      } catch (error) {
        console.log(`Error while fetching monthly charge ${error}`);
      }

      // Only update state if the component is still mounted
      if (isMounted) {
        setMonthlyCharge(noOfCars * perMonthGeneralCharge);
      }
      console.log(`done with getPerMonthCharges`);
    }

    getPerMonthCharges(ownerPhoneNumber, vehicles.length);

    // Cleanup function: runs when the component unmounts
    return () => {
      isMounted = false;
    };
  }, []); // Empty dependency array means this runs once on mount

  // Rest of your component logic...
};
Key Changes Explained
  • Mounted Flag: The isMounted variable stays in scope for the async function, letting us check if the component is still alive before updating state.
  • Cleanup Function: The return () => { isMounted = false; } runs automatically when the component unmounts. It flips the flag to false, so any pending state updates are skipped.
  • Guard Clauses: Before every setMonthlyCharge call, we check if isMounted is true. This ensures we never try to update state on an unmounted component.
Alternative Note: AbortController (For Fetch-Based Calls)

If you were using fetch instead of Firestore's SDK, you could use an AbortController to cancel the network request entirely when the component unmounts. However, Firestore's get() method doesn't support aborting directly, so the mounted flag approach is the most reliable solution here.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:22:29