繁体   English   中英

React useEffect 抛出错误:无法对卸载的组件执行 React 状态更新

[英]React useEffect throws error: Can't perform a React state update on an unmounted component

我正在为我的 spotify api 应用程序使用 react-native,当我想使用axios从我的服务器获取数据时(在useEffect因为我想在组件加载时呈现返回的项目)它抛出错误: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function 所以如果有人知道如何解决这个问题,我会非常感激。

import React, {useEffect, useState} from 'react'
import { View, Text, StyleSheet, Image, FlatList, ActivityIndicator} from 'react-native'
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';

export default function ArtistsCom({route}) {
    const type = route.name.toLowerCase();
    const [time, setTime] = useState('short_term');
    const [access_token, setAccess_token] = useState('');
    const [refresh_token, setRefresh_token] = useState('');
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        setLoading(true);
        AsyncStorage.getItem('refresh_token')
        .then(value => setRefresh_token(value));

        const getDataAsync = async () => {
            const res = await axios.post(`http://localhost:3001/api/refresh`, {
                headers: {
                    body: {
                        refresh_token: refresh_token
                    }
                }
            })
            console.log(res);
            setAccess_token(res.data.access_token);
            return res;
        };
        getDataAsync();
    }, []);

    return (
        <View>
            <View>
                {!loading ? items.map((item, key) => {
                    return (
                        <View key={key} style={{width: 150, height: 150, margin: 10}}>
                            <Image style={{width: '100%', height: '100%'}} source={{uri: type == 'artists' ? item.images[0].url : item.album.images[0].url}} />
                            <View style={{position: 'absolute', bottom: 0, left:4,  height: 20, width: '100%', backgroudColor: 'red'}}><Text style={{color: 'white'}}>{key+1}. {item.name}</Text></View>
                        </View>
                    )
                }) : <Text>Loading...</Text>}
            </View>
        </View>
    )
}

您可以使用取消令牌来取消进行中的请求。

useEffect(() => {
  ...

  // Create cancel token and source
  const CancelToken = axios.CancelToken;
  const source = CancelToken.source();

  const getDataAsync = async () => {
    const res = await axios.post(
      `http://localhost:3001/api/refresh`,
      {
        cancelToken: source.token, // <-- attach cancel token to request
        headers: {
          body: {
            refresh_token: refresh_token
          }
        }
      },
    );
    console.log(res);
    setItems(res.data.items);
    return res;
  };
  getDataAsync();

  // Return useEffect cleanup function to cancel request
  return () => {
    source.cancel('Component unmounted'); // message is optional
  };
}, []);

更新

将异步逻辑包含在try/catch/finally以发出多个请求并处理任何被拒绝的承诺和错误。

useEffect(() => {
  // Create cancel token and source
  const CancelToken = axios.CancelToken;
  const source = CancelToken.source();

  const getDataAsync = async () => {
    setLoading(true);

    try {
      const refresh_token = await AsyncStorage.getItem('refresh_token');
      const res = await axios.post(
        `http://localhost:3001/api/refresh`,
        {
          cancelToken: source.token, // <-- attach cancel token to request
          headers: {
            body: {
              refresh_token
            }
          }
        },
      );

      const { access_token } = res.data;
      setAccess_token(access_token);

      const res2 = await axios.get(`http://localhost:3001/api/top/${type}?time_range=${time}&limit=50&access_token=${access_token}`);
      setItems(res2.data.items);
    } catch(error) {
      // handle any errors, log them, set some state, etc...
    } finally {
      setLoading(false);
    }
  };

  getDataAsync();

  // Return useEffect cleanup function to cancel request
  return () => {
    source.cancel('Component unmounted'); // message is optional
  };
}, [refreshToken]);

我想通了

这是代码:

const type = route.name.toLowerCase();
    const [time, setTime] = useState('short_term');
    const [access_token, setAccess_token] = useState('');
    const [refresh_token, setRefresh_token] = useState('');
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(true);

    const getItems = (ACCESS_TOKEN) => {
        axios.get(`http://localhost:3001/api/top/${type}?time_range=${time}&limit=50&access_token=${ACCESS_TOKEN}`)
        .then(res => {
            setItems(res.data.items);
            setLoading(false);
        })
    }
    
    useEffect(() => {
        setLoading(true);

        const CancelToken = axios.CancelToken;
        const source = CancelToken.source();
        const getRefreshedAccessToken = async() => {
            axios.post(`http://localhost:3001/api/refresh`, {
                cancelToken: source.token,
                headers: {
                    body: {
                        refresh_token: await AsyncStorage.getItem('refresh_token')
                    }
                }
            })
            .then(res => {
                console.log(res.data.access_token);
                setAccess_token(res.data.access_token);
                getItems(res.data.access_token);
            })
            .catch(err => console.log(err))
        };
        getRefreshedAccessToken();

        return () => {
            source.cancel('Component unmounted'); 
        }
    }, [refresh_token]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM