Search code examples
reactjsreact-hooksuse-ref

Why my useEffect is working on localhost but not in production?


I am using the following logic in my app.jsx to check for accessToken and if is not there then I want to run useRefreshToken mutation to get new accessToken with the help of my stored refreshToken cookie stored as httpOnly and secure flag.

I am running the code successfully in my development and all is working as expected checked with console.logs at all the steps.

const [persist] = usePersist()
const token = useSelector(selectCurrentToken)
const effectRan = useRef(false)
const [trueSuccess, setTrueSuccess] = useState(false)

const [refresh, {
    isUninitialized,
    isLoading,
    isSuccess,
    isError,
    error
}] = useRefreshMutation()

useEffect(() => {
    console.log('verifying refresh token useffect running', token, persist)

    if (effectRan.current === true) {
        console.log('verifying refresh token effectRan.current')

        const verifyRefreshToken = async () => {
            console.log('verifying refresh token tryCatch running')
            try {
                await refresh()
                setTrueSuccess(true)
            }
            catch (err) {
                console.error(err)
            }
        }
     if (!token && persist) verifyRefreshToken()
     }

     return () => {
     console.log("EffectRan: ", effectRan.current, token, persist)
     effectRan.current = true
     console.log("EffectRan: ", effectRan.current)
     }
}, [])

However, when I deploy the application after "npm run build" only the first console.log runs indicating that useeffect is running but console.logs in the cleanup functions do not run. I am really pissed as this as I am stuck for more than 10 days. My mind cannot accept why a code is working fine in localhost but not on deployment. I will really appreciate any help.


Solution

  • Your useEffect is only setting the effectRan.current to true in the cleanup function.

    useEffect(() => {
      if (effectRan.current === true) {
        // your logic
      }
    
      return () => {
        effectRan.current = true;
      };
    }, []);
    

    The fact that it only works in developement mode is because the useEffect will run twice on mount because of StrictMode. So the effectRan.current will get set to true when the component unmounts for the first time and then when the it mounts again effectRan.current is true.

    In production StrictMode is disabled and thus will not fire the useEffect twice.

    Instead you could do something like this

    useEffect(() => {
      if (effectRan.current === true) return;
    
      effectRan.current = true;
      // your logic
    }, []);