提问者:小点点

如何解决“无法对未安装的组件执行反应状态更新”


无法对未安装的组件执行React状态更新。这是一个no-op,但它表示应用程序中存在内存泄漏。要修复此问题,请取消useEffect清理函数中的所有订阅和异步任务。在PokemonListItem中(位于PokemonList.jsx:148)

好的,我知道这是一个常见的问题,解决方法应该很简单。我只是不知道如何在我的代码中实现它。

我正在使用React Native和PokéAPI为移动设备制作一种Pokédex。我不确定漏洞在哪里,所以有经验的开发人员请帮忙。

export default function PokemonListItem({ url, Favorite }) {
  const [pokemondata, setData] = React.useState({});
  const [dataReady, setReady] = React.useState(false);
  const [isFavorite, setFavorite] = React.useState(false);

  const favoriteStatus = (bool) => {
    setFavorite(bool);
  };

  const getData = async () => {
    await fetch(url)
      .then((res) => res.json())
      .then((data) => setData(data));

    setReady(true);
  };

  React.useEffect(() => {
    getData();
  }, []);

  more code...
const renderItem = ({ item }) => (
    <TouchableHighlight
      style={{ borderRadius: 10 }}
      underlayColor="#ffc3c2"
      onPress={() => {
        navigation.navigate("Pokémon Details", {
          url: item.url,
        });
      }}
    >
      <PokemonListItem url={item.url} Favorite={FavoriteButton} />
    </TouchableHighlight>
  );

如果需要查看完整代码,可以访问存储库。


共3个答案

匿名用户

试试这个

React.useEffect(() => {
 (async function onMount() {
   await fetch(url)
      .then((res) => res.json())
      .then((data) => setData(data));

    setReady(true);
 })();
}, []);

匿名用户

一种方法似乎是维护一个变量,看看组件是否仍然挂载,这对我来说感觉很臭(React-钩子。无法在未安装的组件上执行React状态更新)-但无论如何,这就是我在代码中看到它的方式...

   let isMounted;

   const getData = async () => {
     await fetch(url)
      .then((res) => res.json())
      .then((data) => { if(isMounted) setData(data)});

     setReady(true);
  };

  React.useEffect(() => {
    isMounted = true;
    getData();
    return () => {
      isMounted = false;
    }
  }, []);

匿名用户

与前面提到的类似,关键点是将状态更新setReady()包装在if(mounted){}块中。

  1. 创建局部变量以表示初始装载状态let mounted=true在您的效果中具有异步调用
useEffect(() => {
  let mounted = true;
  const apiRequest = async (setReady) => {
     let response;
     try {
        response = await APICall();
        if (mounted) {
          setReady(response.data);
        }
     } catch (error) {}
  }
  apiRequest();
  return () => { mounted = false;}
})

https://codesandbox.io/s/upbeat-easley-kl6fv?file=/src/App.tsx

如果删除| | true调用并刷新,您将看到mem leak的错误消失了。