Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React lifecycle with react hooks useEffect

I am currently changing my app files from class with lifecycle events such as componentDidMount to functions with useEffect hooks.

For most files I haven't seen any issues but on the below, I am getting a performance issue, where the app freezes. Zero errors or warnings in the console but my machine and Chrome increases memory used on this tab.

What have I missed?

Old Class based file code

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();
}

New with hooks (causing performance issues)

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

useEffect(() => {
  listener();
  return () => {
    listener();
  };
});

It may also be worth noting that I am using TypeScript with React.

like image 711
Darren Avatar asked Dec 01 '25 23:12

Darren


2 Answers

onAuthUserListener returns a function to unsubscribe. This should be used when component unmounts.

In your code you are not returning the unsubscribe function.

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

So under the useEffect you should assign it properly and use it in useEffect's return.

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
);
like image 62
Joseph D. Avatar answered Dec 04 '25 13:12

Joseph D.


Here might be the error:

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

The question is, what state does need to change in order to trigger a listener(); call?

I think this:

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

Should be transformed into a React Hook. Cheers!

like image 31
Rafael Mora Avatar answered Dec 04 '25 13:12

Rafael Mora



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!