Home > Net >  Should we be using the unsubscribe method returned by Auth.onAuthStateChanged() in firebase to clean
Should we be using the unsubscribe method returned by Auth.onAuthStateChanged() in firebase to clean

Time:05-15

Here is my code:

import React, {useState, useRef, useEffect} from 'react';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { useNavigate } from 'react-router-dom';
import Spinner from '../components/Spinner';

const CreateListing = () => {
  const [geoLocationEnabled, setGeolocationEnabled] = useState(true);
  const [loading, setLoading] = useState(false);
  const [formData, setFormData] = useState({
      type: 'rent',
      name: '',
      bedrooms: 1,
      bathrooms: 1,
      parking: false,
      furnished: false,
      address: '',
      offer: false,
      regularPrice: 0,
      discountedPrice: 0,
      images: {},
      latitude: 0,
      longitude: 0
  });

  const auth = getAuth();
  const navigate = useNavigate();
  const isMounted = useRef(true);

  useEffect(() => {
    if (isMounted.current) {
      onAuthStateChanged(auth, (user) => {
        if (user) {
          setFormData({
            ...formData,
            userRef: user.uid
          });
        }
        else {
          navigate('/sign-in');
        }        
      });                              
    }
    return () => {
      isMounted.current = false;
    }  
  }, []);

  if (loading) {
    return <Spinner />
  }

  return (    
    <div>CreateListing</div>
  )
}
export default CreateListing

I am getting this error:

React Hook useEffect has missing dependencies: 'auth', 'formData', and 'navigate'. Either include them or remove the dependency array. You can also do a functional update 'setFormData(f => ...)' if you only need 'formData' in the 'setFormData' call react-hooks/exhaustive-deps

In order to resolve it I added isMounted as a dependency in the useEffect array AND added the line // eslint-disable-next-line above the dependency array line. This does resolve the warning and everything is working fine. However, there is still a problem with this code. Even though, when the component unmounts the onAuthStatus listener is actually still running, but it's just not able to do anything.

I found a better solution which states that onAuthStatus() returns an unsubscribe method which can be called in useEffect's return function. This will ensure that the listener does get unsubscribed and does cause any memory leaks when the component unmounts.

The link for the onAuthStatus documentation is:

https://firebase.google.com/docs/reference/js/auth.auth.md#authonauthstatechanged

Also, please note that when I click the Unsubscribe link, under Returns:, I get a 404 error...This is unusual

I think the following solution should be better but I'm not sure:

useEffect(()=>{
    const unsub = onAuthStateChanged(auth, (user)=>{
        if (user) {
          setFormData({
            ...formData,
            userRef: user.uid
          });
        }
        else {
          navigate('/sign-in');
        }
    });

    return unsub();
},[]);

Can someone please guide me on this approach? If there's a better solution then kindly share...Thank you in advance.

CodePudding user response:

What you're doing should be OK. Though it's perfectly OK to set up a single listener for your entire app at the global level (without a hook). That listener doesn't really "leak" anything. It just keeps getting called whenever the user's state changes, so you can decide what you want to do for your entire app when that happens.

  • Related