我正在构建一个MERN堆栈应用程序,其中用户必须使用发送到他们的邮箱地址的链接来验证他们的帐户. 用户单击该链接后,它们将被发送到此ActivationPage组件.在这里,我从URL提取令牌,并在useEffect中的POST请求中将其发送到在数据库中创建用户的服务器(MongoDB).

现在的问题是,当组件第一次运行时,它会返回"Your account has been activated successfully!",但几秒钟后,消息会更改为"您的令牌已过期!"因为useEffect再次运行并try 再次创建用户,这导致了错误,因此CATCH块运行.所以,我基本上需要一种让useEffect只运行一次的方法.

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;

推荐答案

如果标志已经运行,我会使用ref来存储它. 使用useRef而不是useState的原因是,我们只需要一个持久变量,并且不希望或需要在更改其值时触发重现器.

import React, { useState, useEffect, useRef } 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');
  const wasAlreadyRequested = useRef(false);

  useEffect(() => {
    const activationEmail = async () => {
      if (activationToken) {
        try {
          wasAlreadyRequested.current = true
          const response = await axios.post(`${serverUrl}/user/activation`, { activationToken });
          console.log(response);
        } catch (error) {
          setError(true);
          console.log(`ERROR: ${error.message}`);
        }
      }
    };
    if (!wasAlreadyRequested.current){
     activationEmail();
    }
  }, [wasAlreadyRequested]);

  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;

Reactjs相关问答推荐

为什么这个'Suspense'子组件在挂起promise解决后会丢失它的状态,而不是呈现?<>

react 派生状态未正确更新

如何将Redux工具包添加到expo (SDK 50)项目?

获取未捕获的错误:Gatsby生产版本上的最小化react 错误#418

React:关于useEffect钩子如何工作的困惑

React-React中是否完全支持基于类的组件?

如何使用TouchStart/TouchEnd在Table ReactJS中交换位置?

React,当我调用handleSubmit()函数时,我正在将application/json和multiform/data中的数据发送到后端,但student_image中没有数据:null

如何清除过滤器搜索的状态

Javascript - 正则表达式不适用于 MAC OS - 编码?

我从 S3 存储桶下载图像时收到错误

无法使axiosmockadapter正常工作

使用 react pro 侧边栏展开折叠菜单

在 React 的父级中多次调用子级时从子级获取数据到父级

如果传递给挂钩的数据需要事先修改,如何使用自定义挂钩?

如何在对话素材ui中设置边框半径?

React CSSTransition 两次创建新页面并在这两个相同的页面上运行转换

如何定制 React 热 toastr ?

如何用实际的br标签替换axios响应中的br标签?

react-three-fiber 场景背景比原图更亮