路由器事件在构造函数上使用时导致错误警告:无法对未安装的组件执行 React 状态更新

Router events cause an error while being used on the constructor Warning: Can't perform a React state update on an unmounted component

我遇到了这个问题,我尝试将其转换为函数,但 states 没有按我预期的那样工作。我该如何解决这个问题?我想在切换路由时创建加载效果而不引起此类问题:

react-dom.development.js?ac89:67 Warning: 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 the componentWillUnmount method.
        at Loading (webpack-internal:///./components/loading.js:83:9)
        at MyApp (webpack-internal:///./pages/_app.js:58:27)
        at StyleRegistry (webpack-internal:///./node_modules/styled-jsx/dist/stylesheet-registry.js:231:34)

这是我的代码:

import Router from "next/router";
import { Component } from "react";
import Loader from "./Loader";

export default class Loading extends Component {
  constructor() {
      super();
      this.state = {
        loader: false
      }
  }

  componentDidMount(){
      // Some page has started loading
      Router.events.on("routeChangeStart", (url) => {
        this.setState({ loader: true });
      });
         // Some page has finished loading
         Router.onRouteChangeComplete = (url) => {
          this.setState({ loader: false });
        };
  }
  componentWillUnmount(){

  }  

  render() {
    return(
      <Loader loading={this.state.loader} />
    );
  }
}

我也试过:

import Router from "next/router";
import { useState } from "react";
import Loader from "./Loader";

export default function Loading (){
  const [loader, setLoader] = useState(false);

  // Some page has started loading
  Router.events.on("routeChangeStart", (url) => {
      setLoader(true);
  });
  // Some page has finished loading
  Router.onRouteChangeComplete = (url) => {
      setLoader(false);
  };

  return <Loader loading={loader} />;
}

您在 componentDidMount 中的代码需要移动到 useEffect 中。此外,当组件卸载时需要清除对路由器事件的订阅,以防止出现您看到的错误。

还建议使用 useRouter 挂钩中的 router 实例,而不是直接访问全局路由器对象。

您的功能组件应大致如下所示。

import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import Loader from "./Loader";

export default function Loading () {
    const [loader, setLoader] = useState(false);
    const router = useRouter();

    useEffect(() => {
        const handleRouteChangeStart = (url) => {
            setLoader(true);
        };
        const handleRouteChangeComplete = (url) => {
            setLoader(false);
        };

        router.events.on("routeChangeStart", handleRouteChangeStart);
        router.events.on("routeChangeComplete", handleRouteChangeComplete);

        // When the component unmounts, unsubscribe from the router events with the `off` method
        return () => {
            router.events.off("routeChangeStart", handleRouteChangeStart);
            router.events.off("routeChangeComplete", handleRouteChangeComplete);
        };
    }, [router]);
  
    return <Loader loading={loader} />;
}