簡體   English   中英

為什么我收到以下 React Native 警告:Can't perform a React state update on an unmounted component

[英]Why am I getting the following React Native warning: Can't perform a React state update on an unmounted component

我正在嘗試構建一個 React Native 應用程序,但我對 React/RN 生態系統仍然有點陌生,所以我可能只是誤解了我遇到的問題的一些明顯問題。

我有一個應用程序,其中許多頁面的結構如下:

<View>
    <NavComponent />
    <View>
        {/* Page component structure/logic here */}
    </View>
</View>

NavComponent負載與可切換導航菜單TouchableOpacity元素像下面這樣:

Go to Screen #1
Go to Screen #2
Go to Screen #3

我遇到的問題(也許這不是 React/RN 工作原理的問題)是,如果我從屏幕 #1 開始,打開導航,轉到屏幕 #2,再次打開導航,然后回到屏幕 #1,即使屏幕 #1 再次出現,屏幕 #1 的實際渲染函數似乎不會再次被調用,並且由於NavComponent是每個屏幕渲染的一部分,當我嘗試要再次從屏幕 #1 打開導航,我收到以下警告:

警告:無法對卸載的組件執行 React 狀態更新。 這是一個空操作,但它表明您的應用程序中存在內存泄漏。 要修復,取消 %s 中的所有訂閱和異步任務。%s,useEffect 清理函數...

同樣,也許我使用該應用程序的方法一開始就有缺陷,但基本上,當我從一個屏幕從導航轉到另一個屏幕時,我總是希望新屏幕從頭開始重新渲染(包括最初的 Ajax 調用數據) .

下面是一個更加充實的屏幕渲染函數示例(它們都遵循相同的基本模式):

const screen1 = ({ navigation }) => {
    const [serverData, setServerData] = useState(null);

    useEffect(() => {
        // getPageData is a custom method I added to axios.
        axios.getPageData('/api/url/here', (data) => {
            setServerData(data);
        });
    }, []);

    if (serverData) {
        const { meta, user, data } = serverData;

        return (
            <View>
                <NavComponent />
                <View style={styles.container}>
                    {/* Page component structure/logic here */}
                </View>
            </View>
        );
    }

    return null;
};

例如,如果我在上面的渲染函數的開頭添加了一個console.log ,它會在第一次加載屏幕時調用,但是如果我轉到屏幕 #2 然后通過導航組件返回屏幕 #1 , console.log不再輸出。 為什么?

對於它的價值,我在NavComponent使用標准的navigation.navigate('ScreenName')從一個屏幕到NavComponent屏幕。

關於如何修復警告(和/或更好地設計應用程序)以便我可以在每個頁面上都有該導航的任何建議將不勝感激。 謝謝你。

您的 api 調用導致警告,在 react/native 生態系統中,當從樹中刪除組件時,開發人員需要取消所有訂閱(事件偵聽器)和異步任務(從網絡獲取數據),這些功能需要由開發人員取消,因為 react/native 無法為您執行此操作。

要在基於類的組件中處理它,您需要執行componentWillUnmount並刪除那里的訂閱

class MyClass extends Component {
   componentWillUnmount() {
     // remove listeners and cancel requests
    }

但是在現代鈎子組件中,您需要返回一個清理函數,一個在 useEffect 中返回的函數,它將被 react 調用以取消您所做的任何訂閱,在您的情況下,只需返回一個清理函數即可為您刪除該警告


  const [mounted, setIsMounted] useState(false)
 useEffect(() => {
        // getPageData is a custom method I added to axios.
        setIsMounted(true)
        axios.getPageData('/api/url/here', (data) => {
            if(isMounted)
             setServerData(data);
        });

        return () => {
             setIsMounted(false)
         }
    }, []);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM