I’m building a MERN stack app in which a user has to verify their account using a link sent to their email address.
After the user clicks on the link, they are sent to this ActivationPage component. Here, I extract the token from the URL and, in a POST request in useEffect
, send it to the server where the user is created in the database (MongoDB).
Now the issue is that when the component first runs, it returns "Your account has been activated successfully!" as it should, however, after a few seconds the message changes to "Your token has expired!" because useEffect
ran again and tried to created the user again which resulted in an error and hence the catch block ran. So, I basically need a way to make useEffect
run only once.
import React, { useState, useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import axios from 'axios';
import { serverUrl } from '../serverUrl';
const ActivationPage = () => {
const [error, setError] = useState(false);
const [searchParams] = useSearchParams();
const activationToken = searchParams.get('token');
useEffect(() => {
const activationEmail = async () => {
if (activationToken) {
try {
const response = await axios.post(`${serverUrl}/user/activation`, { activationToken });
console.log(response);
} catch (error) {
setError(true);
console.log(`ERROR: ${error.message}`);
}
}
};
activationEmail();
}, []);
return (
<div className='w-full h-screen flex justify-center items-center'>
{error ? <p>Your token has expired!</p> : <p>Your account has been activated successfully!</p>}
</div>
);
};
export default ActivationPage;
2
Answers
I would use a ref to store a flag if it was already run.
The reason for using
useRef
instead ofuseState
is that we just need a persistent variable and don’t want or need to trigger a rerender when changing its value.this is a the useeffect code
use this code