代码之家  ›  专栏  ›  技术社区  ›  Darren

使用react hooks useffect的react生命周期

  •  2
  • Darren  · 技术社区  · 7 年前

    我正在更改我的应用程序文件 class 具有生命周期事件,如 componentDidMount 到 functions 具有 useEffect 钩子。

    对于大多数文件,我没有看到任何问题,但在下面,我得到了一个性能问题,应用程序冻结。控制台中没有错误或警告,但我的机器和Chrome增加了此选项卡上使用的内存。

    我错过了什么?

    旧的基于类的文件代码

    listener: any;
    
    componentDidMount() {
      const { firebase } = this.props;
      this.listener = firebase.onAuthUserListener(
        (authUser: any) => {
          localStorage.setItem('authUser', JSON.stringify(authUser));
          this.setState({ authUser });
        },
        () => {
          localStorage.removeItem('authUser');
          this.setState({ authUser: null });
        }
      );
    }
    
    componentWillUnmount() {
      this.listener();
    }
    

    新的带有挂钩(导致性能问题)

    const listener = () => {
      firebase.onAuthUserListener(
        (authUser: any) => {
          localStorage.setItem('authUser', JSON.stringify(authUser));
          setState(authUser);
        },
        () => {
          localStorage.removeItem('authUser');
          setState(null);
        }
      );
    };
    
    useEffect(() => {
      listener();
      return () => {
        listener();
      };
    });
    

    值得注意的是,我使用的是带有react的typescript。

    3 回复  |  直到 7 年前
        1
  •  2
  •   Joseph D.    7 年前

    onAuthUserListener 返回要取消订阅的函数。卸载组件时应使用此选项。

    在代码中,您不会返回unsubscribe函数。

    const listener = () => {
      firebase.onAuthUserListener(..)    // problem here no return
    }
    

    所以在 useEffect 你应该把它分配好并用在 使用效果 回来了。

    const [user, setUser] = React.useState(null);
    
    useEffect(
      () => {
        //             v------ proper assignment.
        const listener = firebase.onAuthUserListener(
          (authUser: any) => {
            localStorage.setItem('authUser', JSON.stringify(authUser));
            setUser(authUser);
          },
          () => {
            localStorage.removeItem('authUser');
            setUser(null);
          }
        );
    
        return () => listener();
      }
      , [] // no deps
    );
    
        2
  •  0
  •   Agney Sidharth yadav    7 年前

    useEffect 需要依赖项数组作为第二个参数,否则它将在每个呈现上继续运行。因为你正在更新状态,所以这只是不断重复

    useEffect(() => {
      listener();
      return () => {
        listener();
      };
    }, []);
    

    Docs

    你可以使用像 Runaway Effects 或eslint,用于静态分析,以便事先确定这些问题。

        3
  •  0
  •   Rafael Mora    7 年前

    可能是以下错误:

    useEffect(() => {
      listener();
      return () => {
        listener();  <--- here
      };
    });
    

    问题是,为了触发 listener(); 打电话?

    我认为:

    const listener = () => {
      firebase.onAuthUserListener(
        (authUser: any) => {
          localStorage.setItem('authUser', JSON.stringify(authUser));
          setState(authUser);
        },
        () => {
          localStorage.removeItem('authUser');
          setState(null);
        }
      );
    };
    

    应该变成一个反应钩。干杯!